diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2020-04-22 12:24:34 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2020-04-22 12:24:36 +0200 |
commit | 72fe3543feb23ae555e08628b70a3fae4da5706c (patch) | |
tree | de8a3f9515a42dc1c8bfd92d9b62a4b6bf6c9b4e | |
parent | b29612fe59f664d9b370dceda1060b1dc1deaff0 (diff) | |
download | libuv-72fe3543feb23ae555e08628b70a3fae4da5706c.tar.gz libuv-72fe3543feb23ae555e08628b70a3fae4da5706c.zip |
unix,win: add uv_library_shutdown()
Make it possible to explicitly tell libuv to release any resources
it's still holding onto (memory, threads, file descriptors, etc.)
Before this commit, cleanup was performed in various destructors.
This commit centralizes the cleanup logic, enabling the addition of
`uv_library_shutdown()`, but maintains the current observable behavior
of cleaning up when libuv is unloaded by means of `dlclose(3)`.
Fixes: https://github.com/libuv/libuv/issues/2763
PR-URL: https://github.com/libuv/libuv/pull/2764
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
-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. */ |