From 44b7c71035a4270510f642923604cc5fed93d20e Mon Sep 17 00:00:00 2001 From: John Barboza Date: Mon, 21 Aug 2017 00:45:19 -0400 Subject: [PATCH] zos: reset epoll data after fork Remove all the epoll file descriptors after a fork since they are no longer valid. The uv__signal_global_once_init function needs to be run after uv__platform_loop_init so that the epoll pthread_atfork handlers get run first. PR-URL: https://github.com/libuv/libuv/pull/1496 Reviewed-By: Ben Noordhuis --- src/unix/loop.c | 2 +- src/unix/os390-syscalls.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/unix/loop.c b/src/unix/loop.c index bcd49242..5b5b0e09 100644 --- a/src/unix/loop.c +++ b/src/unix/loop.c @@ -31,7 +31,6 @@ int uv_loop_init(uv_loop_t* loop) { void* saved_data; int err; - uv__signal_global_once_init(); saved_data = loop->data; memset(loop, 0, sizeof(*loop)); @@ -68,6 +67,7 @@ int uv_loop_init(uv_loop_t* loop) { if (err) return err; + uv__signal_global_once_init(); err = uv_signal_init(loop, &loop->child_watcher); if (err) goto fail_signal_init; diff --git a/src/unix/os390-syscalls.c b/src/unix/os390-syscalls.c index ca539c26..86c6852b 100644 --- a/src/unix/os390-syscalls.c +++ b/src/unix/os390-syscalls.c @@ -120,10 +120,41 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) { } +static void before_fork(void) { + uv_mutex_lock(&global_epoll_lock); +} + + +static void after_fork(void) { + uv_mutex_unlock(&global_epoll_lock); +} + + +static void child_fork(void) { + QUEUE* q; + uv_once_t child_once = UV_ONCE_INIT; + + /* reset once */ + memcpy(&once, &child_once, sizeof(child_once)); + + /* reset epoll list */ + while (!QUEUE_EMPTY(&global_epoll_queue)) { + q = QUEUE_HEAD(&global_epoll_queue); + QUEUE_REMOVE(q); + } + + uv_mutex_unlock(&global_epoll_lock); + uv_mutex_destroy(&global_epoll_lock); +} + + static void epoll_init(void) { QUEUE_INIT(&global_epoll_queue); if (uv_mutex_init(&global_epoll_lock)) abort(); + + if (pthread_atfork(&before_fork, &after_fork, &child_fork)) + abort(); }