develooper Front page | perl.perl5.porters | Postings from January 2001

Re: Does perl really need to use sigsetjmp? (18% performance hit)

Thread Previous | Thread Next
Alan Burlison
January 21, 2001 04:11
Re: Does perl really need to use sigsetjmp? (18% performance hit)
Message ID:
Nicholas Clark wrote:

> Currently it's cheap to sigsetjmp (I'm assuming compared with setting up a
> whole thread) but expensive to keep checking
> Setting up a thread would be expensive, but there's not cost involved in
> checking that the thread you're running in is still running!
> [can we attach enough things to thread exit to tidy up what needs tidying?]

setjmp/sigsetjmp are NOT thread safe and CANNOT be used in a threaded
program.  Period.  Perl5 uses setjmp even when built threaded, and is
therefore irretrievably broken.  If perl6 uses setjmp and also uses
threads, it too will be irretrievably broken.  Here is what our threads
guru has to say on the subject:

> They are designed to work as advertised, but they are MT-usafe in
> principle.
> They are MT-unsafe because if you use siglongjmp(), say, from a signal
> handler, then you have no idea where the application was executing when
> the signal occurred.  It may have been holding a mutex or it may have
> been asleep in a cond_wait().  The siglongjmp leaves the state of the
> application undefined with respect to the locks that are held.
> The short answer is *never use them* in a multithreaded application.

As far as I recollect perls use of setjmp isn't just triggered by eval -
other things such as entering a scope can do it too - is that correct?

I'm not sure that starting a thread per eval context is a sensible thing
to do.  Threads are cheap, but not that cheap.

Basically there is no free lunch here - if we want to use threads and do
exception handling in perl6 we will have to roll our own.  If perl6 has
something akin to the perl5 stack, eval/die will have to be implemented
so that that it rolls back up the stack on die, rather than the current
longjmp hack.

Note that even if we used C++ it wouldn't help us in this case, because
although C++ does exceptions, it knows nothing about threads, mutexes or
CVs.  I suspect the perl6 interpreter loop will look something like:

	while (! end of script) {
		if (at cancellation point) {
			if (signal detected)
				call script signal handler;
			if (something died)
				rollback stack;
		} else {
			do next OP;

In other words the C level signal handler will have to do no more than
setting a flag, as will the implementation of die().  By cancellation
point I mean somewhere that is defined as 'safe', i.e. not holding any
mutexes or waiting on any CVs etc.  I suspect a reasonable thing might
be to have a special 'Now it is safe' opcode that is put out by the
compiler at the appropriate places.  It would be nice if this
corresponded to a syntactic boundary such as an entire statement, so
that for example

	my $a = $b * $c / $d;

was guaranteed to either to be fully evaluated or not at all. 

Alan Burlison

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About