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

Dear Monks,

I would like to alter the name of an output text file on cancellation of the Perl program that has amended this file. Can I write this procedure into the program that is being cancelled?

Replies are listed 'Best First'.
Re: Perl action on cancellation
by Random_Walk (Prior) on Feb 08, 2005 at 12:13 UTC

    It depends on how the script is being killed. A kill -9 on unix can not be trapped, nor can someone pulling the plug out the wall. That aside you can set a signal handler, here is an example that traps the Ctrl-C by setting the $SIG{INT} handler to a subroutine reference. It also has an END block just for fun (any cleanup you do in normal termination could be here and it will get run after the sig handler)

    $ perl -le'$SIG{INT}=sub{print "cleanup"};sleep 100;END{print "goodbye +"}' # here I hit Ctrl-C cleanup goodbye $

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
      Note that doing anything complicated (such as calling "print") from a signal handler can lead to a memory fault and core dump if you're using a perl version < 5.8.

      Another way to install signal handlers is the sigtrap pragma:
      use sigtrap(die INT) END { ##do whatever it is you need to do }
      This will trap Ctrl-C on Unix systems (dunno about Windows) and allow you to put the appropriate action into the END block.
      It is the Control-C as a DOS command that I am thinking about.

        Sorry, let me DOS that for you, looks like Control-C won't break out of the sleep the same way on windows.

        C:\PERL\bin>perl -le"$SIG{INT}=sub{print 'cleanup';exit 0}; while(1){s +leep 1}; END{print 'goodbye'}" # here I hit Control-C cleanup goodbye

        Update

        Now we are a bit more than a one liner we may as well write a proper script. As tirwhan points out it is dangerous to do much in the signal handler. Best just to set a flag that tells your loop to exit.

        #!/usr/bin/perl use strict; use warnings; my $killed=0; $SIG{INT}=sub{$killed++}; while (1) { # this may take some time sleep 1; last if $killed; } if ($killed) { print "cleaning up after getting a sig int\n" }else{ print "finished infinite loop, halting problem next\n" }

        Cheers,
        R.

        Pereant, qui ante nos nostra dixerunt!
Re: Perl action on cancellation
by Anonymous Monk on Feb 08, 2005 at 12:11 UTC
    Not sure what you mean by 'cancelling a program', but does:
    END {defined $old_name and defined $new_name and rename($old_name, $new_name) || warn "Oops: $!"}
    do the trick for you?