Hi Eric, Thanks for the forward.
Ramiro Polla wrote: > > The loop at sigprocmask.c:197 tests signal() on all signals up to NSIG > > for SIG_ERR. On some version of Windows (I haven't checked which one, > > but it affects Windows 2008 Server), a new signal has been added. It > > is the SIGABRT_COMPAT signal, which is the same as SIGABRT [0]. So on > > that loop, signal() is called twice for the same signal. To be clear: The value of SIGABRT under native Windows, 22, has not changed. The visible change is that <signal.h> of newer MSVS contains the line #define SIGABRT_COMPAT 6 > > The abort() on sigprocmask.c:218 has the comment: > > /* The application changed a signal handler while the signal > > was blocked, bypassing our rpl_signal replacement. > > We don't support this. */ > > > > Actually you are changing it yourself. Once for signal 6 (which is the > > value of SIGABRT_COMPAT), and then again for 22 (SIGABRT). Thanks for this analysis. The sigset_t datatype introduced by gnulib has to be adjusted. I propose this patch. Eric, what do you think? 2008-10-18 Bruno Haible <[EMAIL PROTECTED]> * lib/sigprocmask.c (SIGABRT_COMPAT): New macro. (sigismember, sigaddset, sigdelset, sigfillset, rpl_signal): Handle it as an alias for SIGABRT. * lib/sigaction.c (SIGABRT_COMPAT): New macro. (sigaction): Map it to SIGABRT. Reported by Ramiro Polla <[EMAIL PROTECTED]> via Eric Blake. *** lib/sigprocmask.c.orig 2008-10-18 23:29:26.000000000 +0200 --- lib/sigprocmask.c 2008-10-18 23:24:48.000000000 +0200 *************** *** 43,48 **** --- 43,56 ---- # define SIGSTOP (-1) #endif + /* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias + for the signal SIGABRT. Only one signal handler is stored for both + SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ + #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + # undef SIGABRT_COMPAT + # define SIGABRT_COMPAT 6 + #endif + typedef void (*handler_t) (int); /* Handling of gnulib defined signals. */ *************** *** 74,80 **** sigismember (const sigset_t *set, int sig) { if (sig >= 0 && sig < NSIG) ! return (*set >> sig) & 1; else return 0; } --- 82,95 ---- sigismember (const sigset_t *set, int sig) { if (sig >= 0 && sig < NSIG) ! { ! #ifdef SIGABRT_COMPAT ! if (sig == SIGABRT_COMPAT) ! sig = SIGABRT; ! #endif ! ! return (*set >> sig) & 1; ! } else return 0; } *************** *** 91,96 **** --- 106,116 ---- { if (sig >= 0 && sig < NSIG) { + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + *set |= 1U << sig; return 0; } *************** *** 106,111 **** --- 126,136 ---- { if (sig >= 0 && sig < NSIG) { + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + *set &= ~(1U << sig); return 0; } *************** *** 119,125 **** int sigfillset (sigset_t *set) { ! *set = (2U << (NSIG - 1)) - 1; return 0; } --- 144,154 ---- int sigfillset (sigset_t *set) { ! *set = ((2U << (NSIG - 1)) - 1) ! #ifdef SIGABRT_COMPAT ! & ~(1U << SIGABRT_COMPAT) ! #endif ! ; return 0; } *************** *** 241,246 **** --- 270,280 ---- if (sig >= 0 && sig < NSIG && sig != SIGKILL && sig != SIGSTOP && handler != SIG_ERR) { + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + if (blocked_set & (1U << sig)) { /* POSIX states that sigprocmask and signal are both *** lib/sigaction.c.orig 2008-10-18 23:29:26.000000000 +0200 --- lib/sigaction.c 2008-10-18 23:27:42.000000000 +0200 *************** *** 64,69 **** --- 64,77 ---- # define SIGSTOP (-1) #endif + /* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias + for the signal SIGABRT. Only one signal handler is stored for both + SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ + #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + # undef SIGABRT_COMPAT + # define SIGABRT_COMPAT 6 + #endif + /* A signal handler. */ typedef void (*handler_t) (int signal); *************** *** 134,139 **** --- 142,152 ---- return -1; } + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + /* POSIX requires sigaction() to be async-signal-safe. In other words, if an asynchronous signal can occur while we are anywhere inside this function, the user's handler could then call