Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: Handling SIG INT multiple times

by sundialsvc4 (Abbot)
on Oct 01, 2015 at 15:25 UTC ( [id://1143568]=note: print w/replies, xml ) Need Help??


in reply to Handling SIG INT multiple times

Basically (and this is true in any programming language ...) you must treat a signal like “the ringing of the telephone.”   It is a signal that something needs to be done.   Its main purpose in life is not “to wake you up,” but “to ensure that you are not asleep.”   (That is to say, to avoid “busy waiting.”)   It is usually not a good design to do substantial work within a signal handler, since that work will be done completely asynchronously to any other part of the application.   (Signal handlers do not execute concurrently with themselves, as you saw, and if a signal is presented while the handler is still running, the additional signal(s) is usually dropped.)   If the activity that is started by the signal is long-running, interrupts could happen again at any time.   Therefore, the signal handler should not drive that activity.   The actual handler should set a flag and get the hell out of there.

Packages such as POE go a long way toward providing a comprehensive architecture out-of-the-box, but you can also do simpler things.   Most likely, you will want to use a thread to execute the long process (what is now in your signal handler).   When a signal arrives, the signal handler sets a boolean flag to True and strobes a condition-variable.   The main loop of the thread then looks like this:

while (true) { wait for condition variable and reset while (flag is true) { flag = false; // your long-running process .. I-F there is work to do } }

The thread will first await to be awakened.   Then, it will loop and remain awake until the flag remains false, which means that another signal did not arrive in the meantime.   It will then wait on the condition-variable again ... which quite probably has already been tripped again.   Thus, as indicated, the meat-and-potatoes work of the thread might at any point find that there is nothing to do.   The thread will not “stall,” but it might make a few extra do-nothing cycles, and who-cares.

It is easy to see how this can be extended to handle orderly thread termination and wind-up of its affairs:   a “please die” flag is set and the condition is strobed to be sure the thread is awake.

In this explanation, I am not “getting specific to Perl,” and I will leave it to other Monks to write the code for you.   ;-)   These principles are generally true for any programming environment that supports true, pre-emptive threading.

Replies are listed 'Best First'.
Re^2: Handling SIG INT multiple times
by mr_ron (Chaplain) on Oct 02, 2015 at 13:52 UTC

    In theory and somewhat in practice Perl 6 neatly handles this for you with Supplies and taps handling signals in a thread safe sort of way. See "System events exposed as Supplies" in the Perl 6 design documents. The Perl 6 solution inspired me to write some Perl 5 code with similar capability that I have included below. Note that like the Perl 6 solution my code will "as is" do the actual handling of SIGINTs sequentially but it should be quite easy to add some parallel threads if wanted.

    use strict; use warnings; use threads; use Thread::Queue; my $q = Thread::Queue->new(); # A new empty queue my $thr = threads->create( sub { # Thread will loop until no more work while (defined(my $item = $q->dequeue())) { print "starting work on $item\n"; sleep 5; print "finished work on $item\n"; } } ); my $item = 1; { local $SIG{INT} = sub { $q->enqueue($item++) }; kill 'INT', $$; sleep 2; kill 'INT', $$; sleep 2; } $q->enqueue(undef); # I think in more modern Thread::Queue has $q->end $thr->join();
    Ron
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re^2: Handling SIG INT multiple times
by delight (Initiate) on Oct 01, 2015 at 15:54 UTC
    First of all: thank you. I knew/felt that my signal handler was wrong/bad design but I was too lazy for threads. I totally agree with your answer, I guess now I've to code :P. Thank you again!
    A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1143568]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (3)
As of 2024-04-20 01:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found