I've got a moderately complex program which I'm switching to an event-loop architecture, using the Event module. I'm doing something slightly naughty with signal handlers, and I'd like advice on how best to do it with Event.
Before I started using Event, I had a couple of signal handlers that, as part of their work, locally modified the handling of their signal. The interesting case is with SIGTSTP: after doing some application cleanup, it would temporarily reset SIGTSTP to default handling and unblock it and then deliver itself a SIGTSTP. The point of this is that the behaviour looks, from the user's point of view, just like an ordinary ^Z suspension, but the application cleanup gets done along the way. After the program is restarted, the signal handler restores the catching of SIGTSTP and does more bookkeeping before returning. With Event, I'd like the signal handler to operate synchronously as part of the event loop. (The issue of the signal handler possibly being called at an inopportune moment is one of the reasons for moving to an event-loop architecture.) If I do it in the obvious way, replacing "$SIG{TSTP} =" with "Event->signal signal =>", then my signal handler gets called fine, but it fails to restore proper signal handling after temporarily switching it to default handling. I realise that in that I'm breaking one of the documented rules: "A given signal can be handled by %SIG or Event, but not both.". I understand why it doesn't work: %SIG doesn't reflect the actual signal handler, so my "local $SIG{TSTP}" ends up `restoring' undef to $SIG{TSTP} instead of restoring the actual SIGTSTP handler. I want to make it work, in some form. I see four main possible ways for me to achieve the effect I want: 0. Have my own stub signal handler in %SIG, instead of Event handling it. The stub signal handler would do nothing more than trigger an event, the callback for which is the real signal handler that mucks about with %SIG. Result: I get synchronous signal handling, while still retaining control over %SIG. This is inelegant; I'd rather have Event handle the signal directly when I don't need to usurp it. 1. Rewrite my invoke-default-handler function in C, so that it can save and restore the real struct sigaction rather than being limited to what is visible in %SIG. This is cleaner, but means I'd lose some portability. The invoke-default-handler function is actually of wider utility than just this program, so I might implement this anyway so that it can cope with other situations where %SIG isn't the whole story, but I'm concerned about the portability loss for this program. 2. Arrange for Event to be able to cede and retake control of signal handlers. It's a simple enough thing to negotiate. At minimum, Event would need to provide just two new functions: "do you [Event] currently handle signal FOO?" and "rehook signal FOO". This would allow for a much wider range of cases where it is desired to temporarily take over control of a signal from Event. 3. Arrange for %SIG to show *something* for a non-Perl signal handler, so that such handlers can be manipulated by Perl code in the expected manner. (This would actually make my non-working code work without modification.) I'm not sure whether it could be done safely in the general case -- one has to ensure that the non-Perl signal handler can actually be safely used when Perl code tries to install it via %SIG. Even if it's not possible in general, it might be possible for cooperating code to do it, so Event could use that mechanism to achieve option 2 with the means of negotiation being %SIG. Being an engineer, I'm leaning towards attempting 1, 2, and 3 simultaneously. Each of them would be useful even with the others being available, and of course TMTOWTDI. Not knowing Event's internals, though, I'd like commentary from the list. -zefram