Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Re: Detect Stop Button

by sevensven (Pilgrim)
on Nov 26, 2001 at 18:58 UTC ( #127546=note: print w/replies, xml ) Need Help??

in reply to Detect Stop Button

You need to check if your script has lost access to STDOUT.

One easy way to make sure your script will stop is to keep it printing info as it processes (and make sure output is not buffered). The script will die as soon as it tries to access STDOUT and it is no longer available.

I tried to check if the script would get an alarm from Apache, but could not get anything (wich is ok, because Apache docs do not talk about signals to CGI scripts when client disconnects ;^)

I'll put my test code here, just in case you want to fidget with it a bit. If all output is placed into $out instead of dumping it straight to STDOUT, the CGI will not stop running until it normaly ends :

#!/usr/bin/perl use strict; print "Content-type: text/plain\n\n"; $| = 1; #dont buffer output to stdout # playing with signals, no luck sub signal { print LOG "got signal, shuting down\n"; close LOG; } $SIG{INT} = \&signal; $SIG{PIPE} = \&signal; $SIG{ALRM} = \&signal; $SIG{HUP} = \&signal; # check until when did the CGI run with log file open(LOG, '>/usr/local/apache/cgi-bin/log.txt') or die("open : $!"); # dont want LOG file buffering my $old_fh = select(LOG); $| = 1; select($old_fh); my $out = "running cgi, placing outout here\n"; for (my $i=0;$i<20;$i++) { # toogle comments in the 2 following lines to see the CGI stop # print "[$i] test cgi<br>\n"; $out .= "[$i]test cgi<br>\n"; print LOG "[$i] test cgi\n"; sleep(1); } print LOG $out; close LOG;

Update : this sample did not work in IIS (as giulienk reported, tks!), but you only need to add a  or die("gone"); after each print. Perl dies in unix CGI land when it cannot access STDOUT, but it lives on in CGI/IIS windows land. And please remember, the snippet *does not* receive signals from apache, the handlers are there just to show that :-)

-- sevensven or nana korobi, ya oki

Replies are listed 'Best First'.
Re: Re: Detect Stop Button
by giulienk (Curate) on Nov 26, 2001 at 20:10 UTC
    Uhmmm, i got no luck running your example under Win2k. The script goes on working even if i "stopped" the browser.

    Maybe signal handling differs and require some different libraries under windoze?

    Update: i'm using IIS, maybe that's the problem?

Re: Re: Detect Stop Button
by hakkr (Chaplain) on Nov 26, 2001 at 20:24 UTC

    Nice one

    You have made my first perlmonks post worthwhile.
    Constantly printing info may slow me down but it a price worth paying to kill all those zombie cgi.
      hakkr, sevensven's code is just a test that illustrates how to use those signal handlers, and it will let you verify that your server passes the signals to your script appropriately. You don't need to constantly print anything -- that was just part of the test. So, don't slow yourself down needlessly, okay?

      On the other hand, if your script will run for quite a while -- 2+ minutes -- then you really should be printing some invisible characters to keep the browser from timing out. Just another CGI trick...

      Check out sigtrap. After checking out this doc, I'm about to replace all my signal handler code with one sigtrap line!

      Also, check out the great info in the Camel 3 book pp. 412-417 about handling signals and some more specific info on zombie processes.

      One last thing: SIG{PIPE} is the signal which should get sent when a user hits the STOP button on their browser. You really should handle those other important signals too, but SIG{PIPE} is the enemy you're dealing with specifically.

      Update: Here's my new and improved signal handler.
      use Carp; use sigtrap qw(handler croak normal-signals error-signals);
      Also, the signal I get when I hit the STOP button is actually $SIG{TERM}, not $SIG{PIPE}. So, I lied earlier. :)

        Actually, you do have to keep printing as that is the only way you are likely to get SIGPIPE, which is likely the only hope you have if you are already getting defunct CGI processes hanging around.

                - tye (but my friends call me "Tye")
        My script runs for about 1 hr so I had set my Apache TimeOut variable to a huge value (3600). This seems to work for most browsers. I think I'll try your idea of printing blank chars to STDOUT instead. The TimeOut variable effects all requests and probably leaves me with lots of Apache children hanging around.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://127546]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2020-10-24 01:19 GMT
Find Nodes?
    Voting Booth?
    My favourite web site is:

    Results (242 votes). Check out past polls.