[patch/rfa]: Make sigsetjmp/siglongjmp thread-aware (was Re: [patch/rfa]: Add _setjmp/_longjmp macros)

Corinna Vinschen vinschen@redhat.com
Mon Jan 14 20:40:00 GMT 2008


On Jan 13 17:32, Corinna Vinschen wrote:
> Hi,
> 
> SUSv3 defines a _setjmp/_longjmp pair of functions, which are equivalent
> to setjmp/longjmp, except that they shall never manipulate the signal
> mask:
> 
> http://www.opengroup.org/onlinepubs/009695399/functions/_setjmp.html
> 
> The below patch adds _setjmp and _longjmp as macros calling
> sigsetjmp/siglongjmp.

I just found another potential problem with sigsetjmp/siglongjmp.
Both macros are using the sigprocmask function to set and restore
the signal mask.  However, the usage of sigprocmask is unspecified
in multi-threaded processes.  See

http://www.opengroup.org/onlinepubs/009695399/functions/sigprocmask.html

So it looks like the implementation of sigsetjmp/siglongjmp is incorrect
for multi-threaded applications.  Below you'll find a new patch for the
machine/setjmp.h file.  It uses pthread_sigmask instead of sigprocmask
if _POSIX_THREADS is defined, sigprocmask otherwise.  This patch also
contains the patch I sent yesterday.

Tested on Cygwin.  Ok to apply?


Thanks,
Corinna


 	* libc/include/machine/setjmp.h (__SIGMASK_FUNC): Define as
	pthread_sigmask or sigprocmask depending on _POSIX_THREADS.
	(sigsetjmp): Use __SIGMASK_FUNC.
	(siglongjmp): Ditto.
	(_setjmp): Define as macro.
 	(_longjmp): Ditto.


Index: libc/include/machine/setjmp.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/machine/setjmp.h,v
retrieving revision 1.34
diff -u -p -r1.34 setjmp.h
--- libc/include/machine/setjmp.h	7 Nov 2007 21:42:24 -0000	1.34
+++ libc/include/machine/setjmp.h	14 Jan 2008 18:18:23 -0000
@@ -268,6 +268,12 @@ typedef int sigjmp_buf[_JBLEN+2];
 # define _CYGWIN_WORKING_SIGSETJMP
 #endif
 
+#ifdef _POSIX_THREADS
+#define __SIGMASK_FUNC pthread_sigmask
+#else
+#define __SIGMASK_FUNC sigprocmask
+#endif
+
 #if defined(__GNUC__)
 
 #define sigsetjmp(env, savemask) \
@@ -275,7 +281,7 @@ typedef int sigjmp_buf[_JBLEN+2];
             ({ \
               sigjmp_buf *_sjbuf = &(env); \
               ((*_sjbuf)[_SAVEMASK] = savemask,\
-              sigprocmask (SIG_SETMASK, 0, (sigset_t *)((*_sjbuf) + _SIGMASK)),\
+              __SIGMASK_FUNC (SIG_SETMASK, 0, (sigset_t *)((*_sjbuf) + _SIGMASK)),\
               setjmp (*_sjbuf)); \
             })
 
@@ -284,7 +290,7 @@ typedef int sigjmp_buf[_JBLEN+2];
             ({ \
               sigjmp_buf *_sjbuf = &(env); \
               ((((*_sjbuf)[_SAVEMASK]) ? \
-               sigprocmask (SIG_SETMASK, (sigset_t *)((*_sjbuf) + _SIGMASK), 0)\
+               __SIGMASK_FUNC (SIG_SETMASK, (sigset_t *)((*_sjbuf) + _SIGMASK), 0)\
                : 0), \
                longjmp (*_sjbuf, val)); \
             })
@@ -292,15 +298,21 @@ typedef int sigjmp_buf[_JBLEN+2];
 #else /* !__GNUC__ */
 
 #define sigsetjmp(env, savemask) ((env)[_SAVEMASK] = savemask,\
-               sigprocmask (SIG_SETMASK, 0, (sigset_t *) ((env) + _SIGMASK)),\
+               __SIGMASK_FUNC (SIG_SETMASK, 0, (sigset_t *) ((env) + _SIGMASK)),\
                setjmp (env))
 
 #define siglongjmp(env, val) ((((env)[_SAVEMASK])?\
-               sigprocmask (SIG_SETMASK, (sigset_t *) ((env) + _SIGMASK), 0):0),\
+               __SIGMASK_FUNC (SIG_SETMASK, (sigset_t *) ((env) + _SIGMASK), 0):0),\
                longjmp (env, val))
 
 #endif
 
+/* POSIX _setjmp/_longjmp macros, maintained for XSI compatibility.  These
+   are equivalent to sigsetjmp/siglongjmp when not saving the signal mask.
+   New applications should use sigsetjmp/siglongjmp instead. */
+#define _setjmp(env)		sigsetjmp ((env), 0)
+#define _longjmp(env, val)	siglongjmp ((env), (val))
+
 #ifdef __cplusplus
 }
 #endif


-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat



More information about the Newlib mailing list