Bruce Evans wrote:
On Tue, 14 Sep 2010, Tijl Coosemans wrote:
On Thu, Jul 08, 2010 at 11:29:50AM -0400, John Baldwin wrote:
> ...longjmp(3) isn't safe in a signal context...
POSIX says it's supposed to be safe:
"As it bypasses the usual function call and return mechanisms,
longjmp() shall execute correctly in contexts of interrupts, signals,
and any of their associated functions. However, if longjmp() is
invoked from a nested signal handler (that is, from a function
invoked as a result of a signal raised during the handling of another
signal), the behavior is undefined."
It cannot be really safe. It can only execute correctly (where the
definition of "correctly" must not require much more than restoring the
context saved by setjmp(). Consider a signal interrupting almost any
library function that acts on global storage. Only return from the
signal handler (after not clobbering the global storage acted on by the
function) can let the function complete correctly.
POSIX also says:
23731 All accessible objects have values, and all other
components of the abstract machine have state
23732 (for example, floating-point status flags and open
files), as of the time longjmp( ) was called,
23733 except that the values of objects of automatic
storage duration are unspecified if they meet all
23734 the following conditions:
I don't really understand unwinding, but this seems to forbid significant
unwinding. This also expicitly requires broken behaviour for the floating
point state. Keeping the floating point status flags at the time of the
longjmp() is good in general (so that the flags accumulate), but not when
the longjmp() is from a signal handler since signal handlers should get a
clean FP state. Keeping other parts of the FP environment at the time of
the longjmp() is not so good in general, and worse for longjmp() from
signal
handlers. FreeBSD is supposed to keep the FP status flags at the time of
the longjmp() and restore the FP control flags at the time of the setjmp(),
but gets this wrong in more than half of the 24 cases (24 cases = 2 arches
times 3 longjmp()s (also _longjmp() and siglongjmp()) times 4 sets of flags
(mxcsr control/status and i387-environment control/status); only 1 of the
6 longjmp files has been updated to understand mxcsr, and it still uses the
old method of clearing the i386 status flags.
Bruce
The pthread asynchronous cancellation has to unwind from signal handler,
for C language, it has pthread_cleanup_push/pop to handle it. but for
other languages, this is a ugly hack.
I found the standard to unwind stack at here:
http://www.codesourcery.com/public/cxx-abi/abi-eh.html
the unwinding never returns, I think they must take care of the cpu
flags, it does not mean it uses setjmp+longjmp, it uses elf sections
dig out cleanup handler,
but unwinding from signal handler is always trouble, look the bug:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208
It seems i387 would be a serious problem.
The asynchronous cancellation also needs instruction level unwinding
info, gcc flag -fasynchronous-unwind-tables is needed, and some cfi
entry needs to insert into asm code.
http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-assembler/cfi-directives.html
all things can cause very large library size, and if any piece of code
missing the unwinding info, the unwinding can be broken.
I think asynchronous cancellation is non-practical for C++ like
language, it is not constructed in this way.
a realisitic and economy solution would be defer-mode cancellation or
if a user wants asynchronous cancel thread while it is doing pure
computation,it can use sigsetjmp + siglongjmp.
for example, if user is doing some heavy computation, he can:
if (sigsetjmp(&jbuf)) {
pthread_exit(..);
}
/* start doing heavy computation, can be cancelled anywhere: */
...
in signal handler:
it can
void sighandler(int sig) {
siglongjmp(&jbuf)
}
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"