aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/event/process.c3
-rw-r--r--src/nvim/os/signal.c30
2 files changed, 31 insertions, 2 deletions
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index f507e3d71d..51f20b7eac 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -17,8 +17,7 @@
# include "event/process.c.generated.h"
#endif
-// {SIGNAL}_TIMEOUT is the time (in nanoseconds) that a process has to cleanly
-// exit before we send SIGNAL to it
+// Time (ns) for a process to exit cleanly before we send TERM/KILL.
#define TERM_TIMEOUT 1000000000
#define KILL_TIMEOUT (TERM_TIMEOUT * 2)
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index 4abc9cfc36..5295fc03a1 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -2,6 +2,9 @@
#include <stdbool.h>
#include <uv.h>
+#ifndef WIN32
+# include <signal.h> // for sigset_t
+#endif
#include "nvim/ascii.h"
#include "nvim/vim.h"
@@ -29,6 +32,9 @@ static bool rejecting_deadly;
void signal_init(void)
{
+ // Ensure that SIGCHLD is unblocked, else libuv (epoll_wait) may hang.
+ signal_unblock_SIGCHLD();
+
signal_watcher_init(&main_loop, &spipe, NULL);
signal_watcher_init(&main_loop, &shup, NULL);
signal_watcher_init(&main_loop, &squit, NULL);
@@ -151,3 +157,27 @@ static void on_signal(SignalWatcher *handle, int signum, void *data)
break;
}
}
+
+static void signal_unblock_SIGCHLD(void)
+{
+#ifndef WIN32
+ sigset_t mask;
+ sigemptyset(&mask);
+
+ // Work around broken macOS headers. #5243
+# if defined(__APPLE__) && !defined(__clang__) && !defined(__INTEL_COMPILER) \
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+# endif
+
+ sigaddset(&mask, SIGCHLD);
+
+# if defined(__APPLE__) && !defined(__clang__) && !defined(__INTEL_COMPILER) \
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+# pragma GCC diagnostic pop
+# endif
+
+ pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
+#endif
+}