Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Force 2 'ctrl-c's to kill program

by albob (Novice)
on Feb 11, 2013 at 17:11 UTC ( #1018190=perlquestion: print w/ replies, xml ) Need Help??
albob has asked for the wisdom of the Perl Monks concerning the following question:

Hi
I would like to force a user to have to hit ctrl-c twice within 2 seconds in order to kill my program (safety net to prevent unintentional killing of the program). Ideally my code would look like the following:
my $prev_ctrlc = 0; $SIG{'INT'} = \&control_c_observed; sub control_c_observed { if ($prev_ctrlc ==0) { print "Second ctrl-c within 2 seconds required\n"; $prev_ctrlc = 1; sleep (2); $prev_ctrlc = 0; } else { print "This was the 2nd!Dying.\n"; exit; } }

However this obviously does not work (or I would not be hee :)). It looks like the first entry to "control_c_observed" must fully complete before the 2nd interupt request will be serviced.
Does anyone know of a way of achieving my desired behavior?
Thanks
Alan

Comment on Force 2 'ctrl-c's to kill program
Download Code
Re: Force 2 'ctrl-c's to kill program
by jethro (Monsignor) on Feb 11, 2013 at 17:18 UTC

    Haven't tested this, but why not use time() to record the time of the first ctrl-c and break only if the next ctrl-c has time()-$previoustime<=2

      Cheers. I tried someting like that but again it appears that while I am inside my 1st control_c_observed subroutine, the 2nd Ctrl-C only gets serviced after the routine has finished. That is, it does not appear to allow the 2nd ctrl-c affect the sub-routine called by the 1st Ctrl-C. Now, it could be that I implemented it incorrectly!

        So you didn't eliminate the sleep() call? Think about it, why would you still need the sleep call when you know the time the first ctrl-c happened. Without the sleep call the ctrl-c subroutine should be finished almost immediately.

        PS: Using something like sleep() in an interrupt routine is bad design. Interrupt routines should never have a long running time because the code they are interrupting might have expectations of things occuring at a certain speed without seconds-long freezing. For example the user interface

Re: Force 2 'ctrl-c's to kill program
by BrowserUk (Pope) on Feb 11, 2013 at 17:22 UTC

    Try this:

    #! perl -slw use strict; use 5.010; use Time::HiRes qw[ time sleep ]; $|++; $SIG{ INT } = sub { state $last = 0; if( ( time - $last ) > 2 ) { $last = time; return; } die 'Interupted by ^C^C'; }; while( 1 ) { printf "\rtum te tum: %f", time; sleep 0.1; }

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      This certainly seems to work. Must get my head around what it is doing now. Thanks.
        Must get my head around what it is doing now.

        $SIG{ INT } = sub { ## State makes $last a closure; that is a variable that remember' +s its value ## between invocations of the subroutine state $last = 0; ## if the time now is greater than 2 seconds later than the last +time we saw a ^C if( ( time - $last ) > 2 ) { ## Overwrite the last time with the current time $last = time; ## And just return; ignoring this ^C return; } ## However, if it is less than 2 seconds; die. die 'Interupted by ^C^C'; };

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Force 2 'ctrl-c's to kill program
by ww (Bishop) on Feb 11, 2013 at 17:44 UTC
    TIMTOWTDI

    Alternate approach; closer to OP's original (and a surprise to me that it appears to work!)

    #!/usr/bin/perl use 5.016; use warnings; use strict; my $prev_ctrlc = 0; if( ($prev_ctrlc == 0) || ($prev_ctrlc == 1) ) { $SIG{'INT'} = \&control_c_observed; sleep 1; for (1..1e3) { say "\t nothing yet"; sleep 2; } } sub control_c_observed { if ($prev_ctrlc == 0) { print "Second ctrl-c within 2 seconds required\n"; $prev_ctrlc = 1; } else { $prev_ctrlc++; } if ($prev_ctrlc == 2 ) { say "OK, that's two of 'em!"; exit; } }

    Sample run:

    C:\>C:\SQLite\1018190.pl nothing yet nothing yet nothing yet # single tap here Second ctrl-c within 2 seconds required nothing yet nothing yet # double tap here OK, that's two of 'em! C:\>

    The sleep's could annoy your users, as they might seem like the machine is (briefly) locking up.


    If you didn't program your executable by toggling in binary, it wasn't really programming!

      Agreed on sleep. I need to stop using it and start remembering time instead. Cheers

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1018190]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (3)
As of 2014-07-24 02:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (156 votes), past polls