Add workaround for usleep throwing SIGALRM signals
On Solaris, usleep is not thread-safe and will introduce a race condition when used in a multithreaded environment. This manifests as SIGALRM signals escaping from its internal call to sigsuspend. If a signal is missing a handler, the process dies upon receiving it, crashing. The Solaris libc code does something rougly equivalent to this: PreserveSignalHandlers(...); /* Effectively NOPs out SIGALRM */ DisableSIGALRM(...); SetTimer(...); /* Suspends the thread until it receives a SIGALRM signal. When it receives this signal, it both wakes up *and* receives the signal. In this case we don't want to do anything but wake up, so the SIGALRM handler is a NOP. */ sigsuspend(...); RestoreSignalHandlers(...); return; The consequences of this code in a multithreaded context is that if two sleeps are in progress at the same time, one will necessarily finish before the other, *restore the non-existant handlers*, and go on doing its thing. When the other sleep finishes, it won't have a NOP handler to call when waking up, a handler is searched for, none is found, and thus we crash.
This commit is contained in:
parent
a86f5df428
commit
a56c9c57a2
1 changed files with 14 additions and 0 deletions
|
@ -11,6 +11,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <cstring>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
@ -24,6 +25,8 @@ Visual* xVisual;
|
|||
static XVisualInfo xvisinfo;
|
||||
static unsigned long startTime;
|
||||
|
||||
static void nophandler(int signo) {}
|
||||
|
||||
bool Backend_Init(void (*drag_and_drop_callback)(const char *path), void (*window_focus_callback)(bool focus)) {
|
||||
// we're ignoring the hell out of focus and drag & drop
|
||||
xDisplay = XOpenDisplay(NULL);
|
||||
|
@ -35,6 +38,17 @@ bool Backend_Init(void (*drag_and_drop_callback)(const char *path), void (*windo
|
|||
gettimeofday(&time, NULL);
|
||||
startTime = (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||
|
||||
// Disable SIGALRM to compensate for thread-unsafe usleep in Solaris
|
||||
sigset_t mask;
|
||||
struct sigaction act;
|
||||
struct sigaction oldact;
|
||||
act.sa_handler = nophandler;
|
||||
act.sa_flags = 0;
|
||||
sigaction(SIGALRM, &act, &oldact);
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGALRM);
|
||||
sigprocmask(SIG_BLOCK, &mask, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue