Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

The script is running in a while loop. I want to 'catch' window close(upper right cross) signal and perform some clean up before termination. Is that possible in perl?

I heard of END blocks. but that gets executed always regardless of success/failure and I want clean up to be executed only on failure cases like window close,CTRL C/Z,kill signal etc.

I also checked another thread using package 'tk' which is handy for GUI programming,but did not got this case of capturing the window close signal and doing cleanup.

Any help/thoughts are highly appreciated. Thank you.
  • Comment on Catching WINDOW close event and take actions

Replies are listed 'Best First'.
Re: Catching WINDOW close event and take actions
by zentara (Cardinal) on Sep 15, 2011 at 18:56 UTC
    In a Tk gui ( or similarly with other GUI toolkits) you can catch the X button.
    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = new MainWindow; $mw->title("Close test"); $mw->geometry("400x250"); #prevents mw from closing $mw->protocol('WM_DELETE_WINDOW' => sub { print "do stuff here before the exit\n"; exit; }); MainLoop;
    If you are just running an xterm , I don't know if it's possible easily. You probably would have to incorporate Term::ReadKey into your script and manually filter the keys.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      Thank you Zentara. Appreciate it.

      Sorry for a little extension to this question, what is the signal name/code when we kill process using CTRL+ALT+DEL task manager Can we catch it and take cleanup actions

      Appreciate the inputs.

        CTRL-ALT-DEL is usually picked up by the Window Manager, or from console it is the reboot signal. A user cannot intercept that, see Control-Alt-Delete.

        In general, a user process is not able to intercept the Control-Alt-Delete sequence.

        Try this:

        #!/usr/bin/perl use warnings; use strict; sub handler_universal { print "\ngot a signal $_[0]\n"; $SIG{$_[0]} = \&handler_universal; } my @nami = keys(%SIG); #foreach( @nami){ print "$_\t$SIG{$_}\n"; } while(1){ for my $namesig (@nami) {$SIG{$namesig} = \&handler_universal;} }

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh
Re: Catching WINDOW close event and take actions
by onelesd (Pilgrim) on Sep 15, 2011 at 18:29 UTC

    Your term - "failure cases" - is ambiguous. What you probably want to do is catch signals. See perldoc -q signals:

    How do I trap control characters/signals? You don't actually "trap" a control character. Instead, that c +haracter generates a signal which is sent to your terminal's currentl +y foregrounded process group, which you then trap in your process. Signals are documented in + "Signals" in perlipc and the section on "Signals" in the Camel. You can set the values of the %SIG hash to be the functions you + want to handle the signal. After perl catches the signal, it looks +in %SIG for a key with the same name as the signal, then calls the subroutine value for th +at key. # as an anonymous subroutine $SIG{INT} = sub { syswrite(STDERR, "ouch\n", 5 ) }; # or a reference to a function $SIG{INT} = \&ouch; # or the name of the function as a string $SIG{INT} = "ouch"; Perl versions before 5.8 had in its C source code signal handle +rs which would catch the signal and possibly run a Perl function that + you had set in %SIG. This violated the rules of signal handling at that level causing per +l to dump core. Since version 5.8.0, perl looks at %SIG *after* the s +ignal has been caught, rather than while it is being caught. Previous versions of this answe +r were incorrect.
      Thats really nice help. Thank you onelesd.