[Rd] Problem with psignal.c for Windows builds

Radford Neal radford at cs.toronto.edu
Fri Aug 21 21:19:24 CEST 2015

Continuing with problems that I've uncovered while getting pqR to work
on Windows...

The file src/ghuwin32/psignal.c (used only in Windows builds) fails to
use the sigset_t type in all places where it should, using "int" some
places instead.

Here is a diff of the needed corrections:

@@ -253,7 +253,7 @@ sighandler_t signal(int signal_Number, sighandler_t signal_Handler)
 int sigaddset(sigset_t* sigset_Info,int signal_Number)
     if (IS_SIGNAL(signal_Number)) {
-       (*sigset_Info) |= (1 << (signal_Number - 1));
+       (*sigset_Info) |= ((sigset_t)1 << (signal_Number - 1));
        return 0;
     else {
@@ -267,7 +267,7 @@ int sigaddset(sigset_t* sigset_Info,int signal_Number)
 int sigdelset(sigset_t* sigset_Info,int signal_Number)
     if (IS_SIGNAL(signal_Number)) {
-       *sigset_Info &= ~(1<< (signal_Number - 1));
+       *sigset_Info &= ~((sigset_t)1<< (signal_Number-1));
        return 0;
     else {
@@ -295,7 +295,7 @@ int sigfillset(sigset_t* sigset_Info)
 int sigismember(sigset_t* sigset_Info,int signal_Number)
     if (IS_SIGNAL(signal_Number)) {
-       if ( *sigset_Info & (1 << (signal_Number-1)))
+       if ( *sigset_Info & ((sigset_t)1 << (signal_Number-1)))
            return 1;
            return 0;
@@ -380,9 +380,9 @@ int sigprocmask(int mask_Function,sigset_t* sigset_Info,
 /* Set signal mask ========================================================= */
-int sigsetmask(int signal_MaskNew)
+sigset_t sigsetmask(sigset_t signal_MaskNew)
-    int signal_MaskOld = downhill_Sigset_Mask;
+    sigset_t signal_MaskOld = downhill_Sigset_Mask;
     if (sigprocmask(SIG_SETMASK, &signal_MaskNew, NULL) == -1)
        return (int)-1;
@@ -391,7 +391,7 @@ int sigsetmask(int signal_MaskNew)
 /* Add signals to mask ===================================================== */
-int sigblock(int signal_MaskNew)
+sigset_t sigblock(sigset_t signal_MaskNew)
     /* Block a specific group of signals */
     return sigsetmask(downhill_Sigset_Mask|signal_MaskNew);

Now, you may wonder how it's been working with these errors.  The
file src/gnuwin32/fixed/h/psignal.h has the following code:

/* mingw-w64's sys/types.h also defines this and we want this defn */ 
#ifndef _SIGSET_T_
#define _SIGSET_T_
typedef int sigset_t;
#endif  /* Not _SIGSET_T_ */

The comment is unclear as to whether the mingw definition is or is not
the one that is desired (what does "this" refer to?).  Anyway, the
mingw sys/types.h file contains the following code:

#ifndef _SIGSET_T_
#define _SIGSET_T_
#ifdef _WIN64
typedef unsigned long long _sigset_t;
typedef unsigned long   _sigset_t;

#ifdef _POSIX
typedef _sigset_t   	sigset_t;
#endif  /* Not _SIGSET_T_ */

So if the R psignal.h file is included before sys/types, sigset_t will
be defined as "int", not as "unsigned long" or "unsigned long long".

And in fact it seems that R (though not pqR) always includes psignal.h
before sys/types.h (if the latter is included as well).  There's even
this code snippet in src/unix/Rscript.c:

#ifdef WIN32
#include <psignal.h>
/* on some systems needs to be included before <sys/types.h> */

And indeed, with Rtools, you do have to include psignal.h first, since
the mingw sys/types.h defines _SIGSET_T_, preventing psignal.h from
defining sigset_t but does not define sigset_t itself (rather only
_sigset_t), since _POSIX isn't defined.

So current R Core releases (accidentally?) avoid the problem by not
actually using mingw's sigset_t type, but instead always using int.
But it's possible that there is some reason to want to use the type
defined in sys/types.h.

   Radford Neal

More information about the R-devel mailing list