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

Jeff Johnston jjohnstn@redhat.com
Tue Jan 15 07:24:00 GMT 2008


Corinna Vinschen wrote:
> 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?
>

Yes, go ahead.  Thanks.

-- Jeff J.

> 
> 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
> 
> 



More information about the Newlib mailing list