mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
signal_init: Always unblock SIGCHLD. (#5243)
Inherited signal mask may block SIGCHLD, which causes libuv to hang at epoll_wait. Closes #5230 Helped-by: Nicolas Hillegeer <nicolas@hillegeer.com> Helped-by: John Szakmeister <john@szakmeister.net> Note: the #pragma gymnastics are a workaround for broken system headers on macOS. signal.h: int sigaddset(sigset_t *, int); #define sigaddset(set, signo) (*(set) |= __sigbits(signo), 0) sys/_types/_sigset.h: typedef __darwin_sigset_t sigset_t; sys/_types.h: typedef __uint32_t __darwin_sigset_t; /* [???] signal set */ sigset_t is defined as unsigned int, but the sigaddset() ORs it with an int, mixing the types. So GCC generates a sign-conversion warning: sig.c:9:13: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion] (*(&s) |= __sigbits((sigset_t) 20), 0); ~~ ^~~~~~~~~~~~~~~~~~~~~~~~ 1 warning generated. System headers are normally ignored when the compiler generates warnings: https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html > GCC gives code found in system headers special treatment. All warnings, > other than those generated by ‘#warning’ (see Diagnostics), are suppressed > while GCC is processing a system header. Macros defined in a system header > are immune to a few warnings wherever they are expanded. This immunity is > granted on an ad-hoc basis, when we find that a warning generates lots of > false positives because of code in macros defined in system headers. Instead of the #pragma workaround, we could cast the sigset_t pointer: # if defined(__APPLE__) sigaddset((int *)&mask, SIGCHLD); # else sigaddset(&mask, SIGCHLD); # endif but that could break if the headers are later fixed.
This commit is contained in:
parent
0b5a7e4ad5
commit
10a54ad12e
@ -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)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user