This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
Re: [RFA] libc/include/machine/setjmp.h: Only evaluate first parameter to sig{set,long}jmp once
- From: Corinna Vinschen <vinschen at redhat dot com>
- To: newlib at sources dot redhat dot com
- Date: Thu, 17 Mar 2005 12:11:56 +0100
- Subject: Re: [RFA] libc/include/machine/setjmp.h: Only evaluate first parameter to sig{set,long}jmp once
- References: <20050309171237.GP2839@cygbert.vinschen.de>
- Reply-to: newlib at sources dot redhat dot com
Ping?
Corinna
On Mar 9 18:12, Corinna Vinschen wrote:
> Hi,
>
> while debugging current CVS of GDB under Cygwin, I found that the cause
> of the problem I was looking for was this (simplified for readability):
>
> - There's a function call which returns a pointer to a freshly allocated
> sigjmp_buf, let's name it alloc_jmpbuf().
>
> - sigsetjmp is called like this:
>
> sigsetjmp (*alloc_jmpbuf(), 1);
>
> - In libc/include/machine/setjmp.h, sigsetjmp is defined like this:
>
> #define sigsetjmp(env, savemask) ((env)[_SAVEMASK] = savemask,\
> sigprocmask (SIG_SETMASK, 0, (sigset_t *) ((env) + _SIGMASK)),\
> setjmp (env))
>
> A close look into this macro shows, that the first parameter, "env" is
> evaluated three times. In the above situation, that means that three
> times the function alloc_jmpbuf() is invocated, therefore three new
> sigjmp_buf's exist after one call to sigsetjmp.
>
> While the implementation of sigsetjmp is not wrong in the first place,
> it would be better if the implementation would handle cases like the
> above gracefully.
>
> Therefore I propose the below patch. It uses a GCC extension, ({ ... })
> bracketing, to evaluate the incoming parameter only once. I hope that's
> ok for RTEMS as well?
>
>
> Corinna
>
> ChangeLog:
>
> * libc/include/machine/setjmp.h (sigsetjmp): Use GCC extension to
> evaluate first parameter only once.
> (siglongjmp): Ditto.
>
> Index: libc/include/machine/setjmp.h
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/include/machine/setjmp.h,v
> retrieving revision 1.23
> diff -u -p -r1.23 setjmp.h
> --- libc/include/machine/setjmp.h 27 Jan 2005 23:54:42 -0000 1.23
> +++ libc/include/machine/setjmp.h 9 Mar 2005 17:01:08 -0000
> @@ -236,13 +236,22 @@ typedef int sigjmp_buf[_JBLEN+2];
> # define _CYGWIN_WORKING_SIGSETJMP
> #endif
>
> -#define sigsetjmp(env, savemask) ((env)[_SAVEMASK] = savemask,\
> - sigprocmask (SIG_SETMASK, 0, (sigset_t *) ((env) + _SIGMASK)),\
> - setjmp (env))
> +#define sigsetjmp(env, savemask) \
> + ({ \
> + sigjmp_buf *_sjbuf = &(env); \
> + ((*_sjbuf)[_SAVEMASK] = savemask,\
> + sigprocmask (SIG_SETMASK, 0, (sigset_t *)((*_sjbuf) + _SIGMASK)),\
> + setjmp (*_sjbuf)); \
> + })
>
> -#define siglongjmp(env, val) ((((env)[_SAVEMASK])?\
> - sigprocmask (SIG_SETMASK, (sigset_t *) ((env) + _SIGMASK), 0):0),\
> - longjmp (env, val))
> +#define siglongjmp(env, val) \
> + ({ \
> + sigjmp_buf *_sjbuf = &(env); \
> + ((((*_sjbuf)[_SAVEMASK]) ? \
> + sigprocmask (SIG_SETMASK, (sigset_t *)((*_sjbuf) + _SIGMASK), 0)\
> + : 0), \
> + longjmp (*_sjbuf, val)); \
> + })
>
> #ifdef __cplusplus
> }
>
>
> --
> Corinna Vinschen
> Cygwin Project Co-Leader
> Red Hat, Inc.
--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat, Inc.