3

I have a Perl program on Windows that needs to execute cleanup actions on exit. I wrote a signal handler using sigtrap, but it doesn't always work. I can intercept Ctrl-C, but if the machine is rebooted or the program is killed some other way, neither the signal handler nor the END block are run. I've read that Windows doesn't really have signals, and signal handling on windows is sort of a hack in Perl. My question is, how can I handle abnormal termination the Windows way? I want to run my cleanup code regardless of how or why the program terminates (excluding events that can't be caught). I've read that Windows uses events instead of signals, but I can't find information on how to deal with Windows events in Perl.

Unfortunately, I don't have the authority to install modules from CPAN, so I'll have to use vanilla ActiveState Perl. And to make things even more interesting, most of the machines I'm using only have Perl 5.6.1.

Edit: I would appreciate any answers, even if they require CPAN modules or newer versions of Perl. I want to learn about Windows event handling in Perl, and any information would be welcome.

Jonathan
  • 1,163
  • 7
  • 12
  • 1
    Perl 5.6.1.. What is that, like 10 years old? You got Win98/2000/ME on these machines? =) – TLP Dec 05 '11 at 14:31
  • We use Windows XP on all desktop machines. We'll hopefully be on Windows 7 by the time Microsoft stops supporting XP. And believe it or not, some of our machines still use IE6, because a few of our internal apps won't run on anything else. – Jonathan Dec 05 '11 at 16:03
  • 2
    I meant that as a reference.. perl 5.6.1 is about as antiquated as those operating systems. It always makes me wonder why people don't update perl. It's not like it's a good idea not to update any other software. – TLP Dec 05 '11 at 16:20

1 Answers1

3

In all operating systems, you can always abruptly terminate any program. Think of kill -9 command in Unix/Linux. You do that on any program, and it stops instantly. No way to trap it. No way for the program to request a few more operating system cycles for a clean up.

I'm not up on the difference between Unix and Windows signals, but you can imagine why each OS must allow what we call in Unix SIGKILL - a sure and immediate way to kill any program.

Imagine you have a buggy program that intercepts a request to terminate (a SIGTERM in Unix), and it enters a cleanup phase. Instead of cleaning up, the program instead gets stuck in a loop that requests more and more memory. If you couldn't pull the SIGKILL emergency cord, you'd be stuck.

The ultimate SIGKILL, of course is the plug in the wall. Pull it, and the program (along with everything else) comes to a screeching halt. There's no way your program can say "Hmm... the power is out and the machines has stopped running... Better start up the old cleanup routine!"

So, there's no way you can trap every program termination signal, and, your program will have to account for that. What you can do is see if your program needs to do a cleanup before running. On Windows, you can put an entry in the registry when your program starts up, and remove it when it shuts down and does a cleanup. In Unix, you can put a file or directory name starting wit a period in the $ENV{HOME} directory.

Back in the 1980s, I wrote accounting software for a very proprietary OS. When the user pressed the ESCAPE button, we were suppose return immediately to the main menu. If the user was entering an order, and took stuff out of inventory, the transaction would be incomplete, and inventory would be showing the items as being sold even though the order was incomplete. The solution was to check for these incomplete orders the next time someone entered an order, and back out the changes in inventory before entering the new order. Your program may have to do something similar.

David W.
  • 105,218
  • 39
  • 216
  • 337
  • I understand that, but that's not what I was asking. In my original question, I said "excluding events that can't be caught". I know I can't catch the Windows equivalent of SIGKILL or other instantly fatal errors, but I want to be able to catch the equivalent of SIGTERM and similar. But for some reason my signal handler isn't being called except on Ctrl-C. I'd like to learn how to use Windows events directly, rather than going through an incomplete emulation of Unix signals. – Jonathan Dec 06 '11 at 13:13
  • 1
    @Jonathan - Sorry for the confusion. Perl emulates SIGTERM on Cntrl-C, but otherwise, Windows doesn't use signals that can be captured. You can look at [Win32::Events](http://search.cpan.org/~cjm/Win32-IPC/lib/Win32/Event.pm) which ties into Windows Event Handling. That's what Windows sort of uses instead of signals. – David W. Dec 06 '11 at 15:01
  • The reference to Win32::Events is helpful, but the documentation only explains how to create and manipulate events. I need to catch whatever event is generated when the process is killed. Can you point me to any information on that? I've googled "catch windows events in perl" and come up with almost nothing. – Jonathan Dec 07 '11 at 14:08
  • @Jonathan - I'm not a Windows programmer. From what I understand there are very few generic Win32 _signals_. Win32 uses events, and it's up to the client and server to create a set of _events_ they use for communicating. There are certain [pre-defined system wide events](http://www.codeproject.com/KB/winsdk/console_event_handling.aspx) such as `CTRL_C_EVENT`, `CTRL_BREAK_EVENT`, `CTRL_CLOSE_EVENT`, `CTRL_LOGOFF_EVENT`, and `CTRL_SHUTDOWN_EVENT`. You can try trapping these with `Win32::Events. – David W. Dec 07 '11 at 19:49