diff --git a/include/uv.h b/include/uv.h index c9c5c9ab..014ea96e 100644 --- a/include/uv.h +++ b/include/uv.h @@ -807,8 +807,10 @@ struct uv_getaddrinfo_s { * * Return code 0 means that request is accepted and callback will be called * with result. Other return codes mean that there will not be a callback. - * Input arguments may be released after return from this call. Callback - * must not call freeaddrinfo. + * Input arguments may be released after return from this call. + * + * uv_freeaddrinfo() must be called after completion to free the addrinfo + * structure. */ int uv_getaddrinfo(uv_loop_t*, uv_getaddrinfo_t* handle, @@ -817,6 +819,8 @@ struct uv_getaddrinfo_s { const char* service, const struct addrinfo* hints); +void uv_freeaddrinfo(struct addrinfo* ai); + /* uv_spawn() options */ typedef struct uv_process_options_s { uv_exit_cb exit_cb; /* Called after the process exits. */ diff --git a/src/unix/core.c b/src/unix/core.c index 39d5641f..80b3bf6e 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -600,8 +600,6 @@ static int uv_getaddrinfo_done(eio_req* req) { handle->cb(handle, handle->retcode, res); - freeaddrinfo(res); - return 0; } @@ -668,6 +666,11 @@ int uv_getaddrinfo(uv_loop_t* loop, } +void uv_freeaddrinfo(struct addrinfo* ai) { + freeaddrinfo(ai); +} + + /* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ int uv__socket(int domain, int type, int protocol) { #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) diff --git a/src/unix/darwin.c b/src/unix/darwin.c index 6bc122cc..af72b4b0 100644 --- a/src/unix/darwin.c +++ b/src/unix/darwin.c @@ -19,6 +19,7 @@ */ #include "uv.h" +#include "internal.h" #include #include diff --git a/src/win/getaddrinfo.c b/src/win/getaddrinfo.c index 3d313420..1416f04d 100644 --- a/src/win/getaddrinfo.c +++ b/src/win/getaddrinfo.c @@ -216,12 +216,17 @@ complete: /* finally do callback with converted result */ handle->getaddrinfo_cb(handle, uv_ret, (struct addrinfo*)alloc_ptr); + uv_unref(loop); +} + + +void uv_freeaddrinfo(struct addrinfo* ai) { + char* alloc_ptr = (char*)ai; + /* release copied result memory */ if (alloc_ptr != NULL) { free(alloc_ptr); } - - uv_unref(loop); } diff --git a/test/benchmark-getaddrinfo.c b/test/benchmark-getaddrinfo.c index c2a88797..892c14d1 100644 --- a/test/benchmark-getaddrinfo.c +++ b/test/benchmark-getaddrinfo.c @@ -52,6 +52,8 @@ static void getaddrinfo_cb(uv_getaddrinfo_t* handle, int status, if (calls_initiated < TOTAL_CALLS) { getaddrinfo_initiate(handle); } + + uv_freeaddrinfo(res); } diff --git a/test/test-getaddrinfo.c b/test/test-getaddrinfo.c index 4f0514f5..2a8c94e7 100644 --- a/test/test-getaddrinfo.c +++ b/test/test-getaddrinfo.c @@ -45,6 +45,7 @@ static void getaddrinfo_basic_cb(uv_getaddrinfo_t* handle, ASSERT(handle == getaddrinfo_handle); getaddrinfo_cbs++; free(handle); + uv_freeaddrinfo(res); } @@ -65,6 +66,7 @@ static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle, ASSERT (i < CONCURRENT_COUNT); free(data); + uv_freeaddrinfo(res); getaddrinfo_cbs++; }