This patch causes mon to run alerts asychronously.

diff -ur 0.99.1/mon work/mon
--- 0.99.1/mon  Sat Aug 18 15:37:53 2001
+++ work/mon    Fri Sep  7 10:20:26 2001
@@ -2772,10 +2775,25 @@
     my ($summary, $tmnow, $buf);
 
     $tmnow = time;
+
+    #
+    # Since this only waits while a monitor is running, alerts which are
+    # run while no monitors are active will become zombies.  They'll be
+    # reaped when a monitor is next started up.  This should be harmless
+    # with any normal configuration.  It could be fixed by either
+    # removing this test (and so always checking for dead kids, even
+    # when no monitors are active), or by integrating non-monitors into
+    # %runningpid and testing that rather than %running here.
+    #
     return if (keys %running == 0);
 
     while ((my $p = waitpid (-1, &WNOHANG)) >0)
     {
+       if (!exists $runningpid{$p}) {
+           debug (1, "reaped non-monitor, pid $p status $?\n");
+           next;
+       }
+
        my ($group, $service) = split (/\//, $runningpid{$p});
        my $sref = \%{$watch{$group}->{$service}};
 
@@ -4531,14 +4549,39 @@
     syslog ("alert", "calling $alerttype $a for" .
        " $args{group}/$args{service} ($alert,$args{args}) $summary");
 
-    my $pid = open (ALERT, "|-");
+    #
+    # As a simple way to avoid blocking while writing data to the alert,
+    # I fork an extra kid to do the job.  First I fork one kid.  This
+    # one forks another which execs the alert, then it writes the data
+    # to it.  The server process continues without waiting.
+    #
+    # XXX This could be done more efficiently by forking a single kid to
+    # exec the alert, then using the main select loop to write data to
+    # it.
+    #
+    my $pid = fork;
     if (!defined $pid) {
        syslog ('err', "could not fork: $!");
        return undef;
     }
 
     #
-    # child, the actual alert
+    # first child, fork off the alert and feed data to it
+    #
+    if ($pid == 0) {
+       $pid = open (ALERT, "|-");
+       if (!defined $pid) {
+           syslog ('err', "could not fork: $!");
+           exit;
+       }
+       if ($pid != 0) {
+           print ALERT $args{"output"};
+           exit;
+       }
+    }
+
+    #
+    # second child, the actual alert
     #
     if ($pid == 0) {
        #
@@ -4599,13 +4642,6 @@
        }
        exit;
     }
-
-    #
-    # this will block if the alert is sucking gas
-    #
-    print ALERT $args{"output"};
-    close (ALERT);
-    waitpid $pid, 0;
 
     #
     # test alerts don't count

-- 
Roderick Schertler
[EMAIL PROTECTED]

Reply via email to