diff options
-rw-r--r-- | docs/src/misc.rst | 16 | ||||
-rw-r--r-- | include/uv.h | 2 | ||||
-rw-r--r-- | src/threadpool.c | 4 | ||||
-rw-r--r-- | src/unix/aix.c | 2 | ||||
-rw-r--r-- | src/unix/bsd-proctitle.c | 7 | ||||
-rw-r--r-- | src/unix/internal.h | 2 | ||||
-rw-r--r-- | src/unix/no-proctitle.c | 3 | ||||
-rw-r--r-- | src/unix/proctitle.c | 2 | ||||
-rw-r--r-- | src/unix/signal.c | 4 | ||||
-rw-r--r-- | src/uv-common.c | 16 | ||||
-rw-r--r-- | src/uv-common.h | 4 | ||||
-rw-r--r-- | src/win/signal.c | 5 | ||||
-rw-r--r-- | src/win/util.c | 4 | ||||
-rw-r--r-- | test/task.h | 1 |
14 files changed, 64 insertions, 8 deletions
diff --git a/docs/src/misc.rst b/docs/src/misc.rst index 7640b8b0..7bf71b12 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -233,6 +233,22 @@ API sure the allocator is changed while no memory was allocated with the previous allocator, or that they are compatible. +.. c:function:: void uv_library_shutdown(void); + + .. versionadded:: 1.38.0 + + Release any global state that libuv is holding onto. Libuv will normally + do so automatically when it is unloaded but it can be instructed to perform + cleanup manually. + + .. warning:: Only call :c:func:`uv_library_shutdown()` once. + + .. warning:: Don't call :c:func:`uv_library_shutdown()` when there are + still event loops or I/O requests active. + + .. warning:: Don't call libuv functions after calling + :c:func:`uv_library_shutdown()`. + .. c:function:: uv_buf_t uv_buf_init(char* base, unsigned int len) Constructor for :c:type:`uv_buf_t`. diff --git a/include/uv.h b/include/uv.h index 3a2a504d..fb51dfd6 100644 --- a/include/uv.h +++ b/include/uv.h @@ -265,6 +265,8 @@ typedef void* (*uv_realloc_func)(void* ptr, size_t size); typedef void* (*uv_calloc_func)(size_t count, size_t size); typedef void (*uv_free_func)(void* ptr); +UV_EXTERN void uv_library_shutdown(void); + UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, diff --git a/src/threadpool.c b/src/threadpool.c index a8f433f0..0998938f 100644 --- a/src/threadpool.c +++ b/src/threadpool.c @@ -160,8 +160,8 @@ static void post(QUEUE* q, enum uv__work_kind kind) { } +void uv__threadpool_cleanup(void) { #ifndef _WIN32 -UV_DESTRUCTOR(static void cleanup(void)) { unsigned int i; if (nthreads == 0) @@ -181,8 +181,8 @@ UV_DESTRUCTOR(static void cleanup(void)) { threads = NULL; nthreads = 0; -} #endif +} static void init_threads(void) { diff --git a/src/unix/aix.c b/src/unix/aix.c index 417ee551..6b4594b4 100644 --- a/src/unix/aix.c +++ b/src/unix/aix.c @@ -926,7 +926,7 @@ int uv_get_process_title(char* buffer, size_t size) { } -UV_DESTRUCTOR(static void free_args_mem(void)) { +void uv__process_title_cleanup(void) { uv__free(args_mem); /* Keep valgrind happy. */ args_mem = NULL; } diff --git a/src/unix/bsd-proctitle.c b/src/unix/bsd-proctitle.c index 0ce47c8f..723b81c0 100644 --- a/src/unix/bsd-proctitle.c +++ b/src/unix/bsd-proctitle.c @@ -37,6 +37,13 @@ static void init_process_title_mutex_once(void) { } +void uv__process_title_cleanup(void) { + /* TODO(bnoordhuis) uv_mutex_destroy(&process_title_mutex) + * and reset process_title_mutex_once? + */ +} + + char** uv_setup_args(int argc, char** argv) { process_title = argc > 0 ? uv__strdup(argv[0]) : NULL; return argv; diff --git a/src/unix/internal.h b/src/unix/internal.h index 598554b6..402ee877 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -106,10 +106,8 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); #if defined(__clang__) || \ defined(__GNUC__) || \ defined(__INTEL_COMPILER) -# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration # define UV_UNUSED(declaration) __attribute__((unused)) declaration #else -# define UV_DESTRUCTOR(declaration) declaration # define UV_UNUSED(declaration) declaration #endif diff --git a/src/unix/no-proctitle.c b/src/unix/no-proctitle.c index 165740ca..32aa0af1 100644 --- a/src/unix/no-proctitle.c +++ b/src/unix/no-proctitle.c @@ -29,6 +29,9 @@ char** uv_setup_args(int argc, char** argv) { return argv; } +void uv__process_title_cleanup(void) { +} + int uv_set_process_title(const char* title) { return 0; } diff --git a/src/unix/proctitle.c b/src/unix/proctitle.c index d124d3c7..4ee991fc 100644 --- a/src/unix/proctitle.c +++ b/src/unix/proctitle.c @@ -145,7 +145,7 @@ int uv_get_process_title(char* buffer, size_t size) { } -UV_DESTRUCTOR(static void free_args_mem(void)) { +void uv__process_title_cleanup(void) { uv__free(args_mem); /* Keep valgrind happy. */ args_mem = NULL; } diff --git a/src/unix/signal.c b/src/unix/signal.c index 1e7e8ac5..1c83e095 100644 --- a/src/unix/signal.c +++ b/src/unix/signal.c @@ -77,7 +77,7 @@ static void uv__signal_global_init(void) { } -UV_DESTRUCTOR(static void uv__signal_global_fini(void)) { +void uv__signal_cleanup(void) { /* We can only use signal-safe functions here. * That includes read/write and close, fortunately. * We do all of this directly here instead of resetting @@ -98,7 +98,7 @@ UV_DESTRUCTOR(static void uv__signal_global_fini(void)) { static void uv__signal_global_reinit(void) { - uv__signal_global_fini(); + uv__signal_cleanup(); if (uv__make_pipe(uv__signal_lock_pipefd, 0)) abort(); diff --git a/src/uv-common.c b/src/uv-common.c index 5cb1a8c8..f69a2c1d 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -821,3 +821,19 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } + + +#ifdef __GNUC__ /* Also covers __clang__ and __INTEL_COMPILER. */ +__attribute__((destructor)) +#endif +void uv_library_shutdown(void) { + static int was_shutdown; + + if (was_shutdown) + return; + + uv__process_title_cleanup(); + uv__signal_cleanup(); + uv__threadpool_cleanup(); + was_shutdown = 1; +} diff --git a/src/uv-common.h b/src/uv-common.h index f08fb8ae..28cc852c 100644 --- a/src/uv-common.h +++ b/src/uv-common.h @@ -201,6 +201,10 @@ int uv__next_timeout(const uv_loop_t* loop); void uv__run_timers(uv_loop_t* loop); void uv__timer_close(uv_timer_t* handle); +void uv__process_title_cleanup(void); +void uv__signal_cleanup(void); +void uv__threadpool_cleanup(void); + #define uv__has_active_reqs(loop) \ ((loop)->active_reqs.count > 0) diff --git a/src/win/signal.c b/src/win/signal.c index 276dc609..3d9f92cf 100644 --- a/src/win/signal.c +++ b/src/win/signal.c @@ -46,6 +46,11 @@ void uv_signals_init(void) { } +void uv__signal_cleanup(void) { + /* TODO(bnoordhuis) Undo effects of uv_signal_init()? */ +} + + static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { /* Compare signums first so all watchers with the same signnum end up * adjacent. */ diff --git a/src/win/util.c b/src/win/util.c index aaa7ba03..ff8a28b4 100644 --- a/src/win/util.c +++ b/src/win/util.c @@ -361,6 +361,10 @@ char** uv_setup_args(int argc, char** argv) { } +void uv__process_title_cleanup(void) { +} + + int uv_set_process_title(const char* title) { int err; int length; diff --git a/test/task.h b/test/task.h index 27b73103..e95e3bde 100644 --- a/test/task.h +++ b/test/task.h @@ -230,6 +230,7 @@ typedef enum { do { \ close_loop(uv_default_loop()); \ ASSERT(0 == uv_loop_close(uv_default_loop())); \ + uv_library_shutdown(); \ } while (0) /* Just sugar for wrapping the main() for a task or helper. */ |