[RFA] libc/include/machine/setjmp.h: Only evaluate first parameter to sig{set,long}jmp once
Corinna Vinschen
vinschen@redhat.com
Wed Mar 9 17:13:00 GMT 2005
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.
More information about the Newlib
mailing list