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

Hi Perl Monks,

I tried using signals on Windows XP. I was thinking to use signal as a way for IPC to have the target process do something upon a signal and keep alive. But I found that whenever a process receives a signal from another process, it exits right away without **doing anything (i.e., it is not processing the code in the handler)** and **not keeping alive**

I verified that the process only reacts on the signals having been associated with handlers.

My questions:
1. How can I make the code in the handler to be executed?
2. Is there a way to keep the process alive after receiving the signal?

Here is the example, run this script in one command line window first.

#!c:\perl\bin\perl.exe #Assign signal handlers $SIG{'NUM12'} = 'handler'; $SIG{'CHLD'} = 'handler'; print "List current SIG handlers...\n"; while ( my ($key, $value) = each(%SIG) ) { print "$key => $value\n" if ($value ne ''); } print "My PID is $$. I go sleep and wait for signals and ...\n"; while(1) { sleep; } sub handler{ local ($sig) = @_; # Problem: This line never printed. print "I am doing something for SIG $sig....\n"; }
Then, run this in another command line window:
perl -e "kill CLD, <the PID displayed in the first window>"
What happened was--whenever the first process received the signal, it exit right away without printing any message from the handler.

Any idea?

Thanks
PerlSearcher


Update:
Thanks all for the replies.

On Win32, I found it only reacted on the signals I associated with handlers. That means the signal number ideed got sent over to the other process by the KILL function.

Also, I tested all the signals in the %SIG by associating all the signals to a handler. Here is what I found--when a Win32 Perl process gets a signal (through emulation), all of them caused the process to exit without executing the code in handler, except for the following signals, in which cases, the process receiving the signals just do nothing (neither executing the code in handler nor exiting).
--BREAK
--INT
--QUIT
--TERM

In summary, it is not a good idea to use signal on Win32 for IPC, if you have other approaches to achieve the goal.

Replies are listed 'Best First'.
Re: Using Signals on Windows XP
by Corion (Patriarch) on Jul 27, 2007 at 22:19 UTC

    Quoting perlwin32: Signal handling may not behave as on Unix platforms (where it doesn't exactly "behave", either :). For instance, calling die() or exit() from signal handlers will cause an exception, since most implementations of signal() on Win32 are severely crippled. Thus, signals may work only for simple things like setting a flag variable in the handler. Using signals under this port should currently be considered unsupported.

    The kill command does not really send a signal under Win32 but as on all systems, SIGKILL is not something you can catch and handle. Your process never really "sees" that signal, it just gets stopped and removed from the set of active processes.

    Update: I just saw you're not sending a SIGKILL, so it seems that the signal emulation across processes on Win32 is just SIGKILL no matter what number you hand to kill.

Re: Using Signals on Windows XP
by ikegami (Patriarch) on Jul 28, 2007 at 05:58 UTC

    To add to what Corion said, Windows doesn't have signals. Anything you see in Perl is an emulation. As with almost all emulations, there are flaws and limitations. Windows is based around messages sent to windows (due to its origins as a windowing environment running over DOS).

    That means you'll probably have better luck by using Windows calls directly. WaitForSingleObject and family allows you to wait for child processes to die by waiting on a process handle. This is can be obtained when creating the child and by other means. It supports a timeout.

Re: Using Signals on Windows XP
by BrowserUk (Patriarch) on Jul 28, 2007 at 11:03 UTC

    As ikegami points out, signals don't exist on win32, so what this is detailing is just an emulation. You can only use it from and between perl programs; and attempting to use it for anything other than 'Is the process still alive'; and 'kill process with extreme prejudice'; really doesn't work. #

    I have a postit stuck on my wall that reads:

    Win32 trappable sigs: BREAK/21, INT/2, QUIT/3, TERM/15; Others (except 0) always fatal!

    Going by the faded color of the postit, it's probably at least 2 years old. I do remember it was frustratingly hard to verify this information. Anyone who wants to try might find this code useful as a starting point.

    SigCheck.pl

    #! perl -slw use strict; use Config; $|++; sub startKid { warn "starting kid\n"; my $pid = system 1, '/perl/bin/perl.exe trapSigs.pl' or die $!; sleep 0; warn "starting kid\n"; return $pid; } my $pid = startKid; for my $signo ( sort {$a<=>$b} split ' ', $Config{ sig_num } ) { warn "Skipping $signo\n\n" and next if $signo == 15 or $signo == 2 +1; warn "Trying $signo\n"; warn "kill $signo, $pid returned: ", kill( $signo, $pid ), "\n"; for( 1 .. 3 ) { my $rv = kill 0, $pid; print "Attempt $_ at kill 0, $pid returned: ", $rv; last unless $rv; sleep 1; } if( kill 0, $pid ) { warn "signal no: $signo was non-fatal\n\n"; } else { warn "signal no: $signo was fatal\n\n"; $pid = startKid; warn "Restarted kid: $pid\n"; sleep 1; } }

    TrapSigs.pl

    #! perl -slw use strict; use Config; print <>; close STDIN; my @sigs = split ' ', $Config{ sig_name }; shift @sigs; for ( @sigs ) { warn "Installing signal handler for $_\n"; eval qq[\$SIG{ $_ } = sub{ warn "Signal $_ received\n"; } ]; } my $count; while( 1 ) { $count += 1 for 1.. 1e6; warn $count; sleep 3; }

    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.