Front page | perl.perl5.porters |
Postings from March 2008
safely supporting POSIX SA_SIGINFO
Thread Next
From:
Nicholas Clark
Date:
March 10, 2008 16:31
Subject:
safely supporting POSIX SA_SIGINFO
Message ID:
20080310233146.GK79799@plum.flirble.org
Some years ago Jarkko supplied patches to provide support for the POSIX
SA_SIGINFO feature in Perl, passing the extra data to the Perl signal handler.
Unfortunately, it only works with "unsafe" signals, because under safe
signals, by the time Perl gets to run the signal handler, the extra
information has been lost. Moreover, it's not easy to store it somewhere,
as you can't call mutexs, or do anything else fancy, from inside a signal
handler.
But there are a few things you can do in a signal handler:
http://www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_04.html#tag_02_04_03
One of them is write(). (Annoyingly one of them isn't writev(), despite the
fact that the gospel according to the Open Group says
The writev() function shall be equivalent to write(), except as described
below.
http://www.opengroup.org/onlinepubs/000095399/functions/writev.html
and nowhere below (or above) does it say "not safe inside signal handlers"
But write() is. And the spec says that non-blocking writes smaller than
PIPE_BUF are atomic - it's all or nothing:
http://www.opengroup.org/onlinepubs/000095399/functions/write.html
So it strikes me that we could provide safe SA_SIGINFO support
0: Provide global variables for two file descriptors
1: When the first request is made via sigaction for SA_SIGINFO, create a pipe,
store the reader in one, the writer in the other
2: In the "safe" signal handler (Perl_csighandler()/S_raise_signal()), if
the siginfo_t pointer non-NULL, and the writer file handle is open,
a: serialise signal number,
struct siginfo_t (or at least the parts we care about)
into a small auto char buff
b: write() that (non-blocking) to the writer fd
i) if it writes 100%, flag the signal in a counter of "signals on the
pipe" akin to the current per-signal-number counts
ii) if it writes 0%, assume the pipe is full. Flag the data as lost?
iii) if it writes partially, croak a panic, as your OS is broken.
3: in the regular PERL_ASYNC_CHECK() processing, if there are "signals on
the pipe", read the data out, deserialise, build the Perl structures on
the stack (code in Perl_sighandler(), the "unsafe" handler), and call as
usual.
I think that this gets us decent SA_SIGINFO support, without the current risk
of running Perl code inside the signal handler context. (With all the dangers
of things like malloc corruption that that currently offers us)
Thoughts?
Nicholas Clark
Thread Next
-
safely supporting POSIX SA_SIGINFO
by Nicholas Clark