Work around GNO libc's buggy sigprocmask implementation by defining our own version of it. This should fix issues where hush could hang in wait() calls.

The sigprocmask implementation in GNO 2.0.6 libc has bugs that cause it to never actually unblock signals that have been blocked. This was causing many signals to remain blocked when they shouldn't be, particularly after running signal handlers.

This problem combined with a kernel issue (wait() calls won't recognize that a child has finished if SIGCHLD is blocked) to cause hangs in certain conditions.

This patch works around these issues by defining our own non-buggy version of sigprocmask in place of libc's.
This commit is contained in:
Stephen Heumann 2015-01-15 18:02:33 -06:00
parent f88111e789
commit 656769d136
1 changed files with 35 additions and 0 deletions

View File

@ -53,3 +53,38 @@ void FAST_FUNC kill_myself_with_sig(int sig)
raise(sig);
_exit(sig | 128); /* Should not reach it */
}
#ifdef __GNO__
/* Include our own version of sigprocmask, because the one in
* GNO 2.0.6 libc is broken for SIG_SETMASK and SIG_UNBLOCK cases
* (it will never unblock any signals). */
int sigprocmask(int how, const sigset_t *set, sigset_t *oset)
{
sigset_t oldmask;
if (set) {
switch (how) {
case SIG_BLOCK:
oldmask = sigblock(*set);
break;
case SIG_SETMASK:
oldmask = sigsetmask(*set);
break;
case SIG_UNBLOCK:
oldmask = sigblock(0);
sigsetmask(oldmask & ~*set);
break;
default:
errno = EINVAL;
return -1;
}
} else if (oset) {
oldmask = sigblock(0);
}
if (oset)
*oset = oldmask;
return 0;
}
#endif