1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
--- amavis/amavisd.in.orig Sun Aug 25 23:45:58 2002
+++ amavis/amavisd.in Sun Aug 25 23:50:56 2002
@@ -123,7 +123,7 @@
#
# Client/server/daemon related
-my ($socketname, $parentpid, $tmppid) = ("@sockname@", 0, 0);
+my ($socketname, $parentpid, $diedpid, $tmppid) = ("@sockname@", 0, 0, 0);
# flag to indicate compressing file format
my $some_compression = 0;
@@ -172,15 +172,19 @@
#
# SIGCHLD handler
sub deadbabe {
- for (;;) {
- my $childpid = wait;
- last if $childpid < 0;
- $child_status{$childpid} = $?;
- $child_etime{$childpid} = time;
- }
+ do {
+ $tmppid = waitpid(-1, &WNOHANG);
+ } while ($tmppid > 0);
+ $diedpid = 1;
$SIG{CHLD} = \&deadbabe;
+# stupid sys5 resets the signal when called - but only -after- the wait...
}
-$SIG{CHLD} = \&deadbabe;
+# Catch any dead child process
+
+# If IGNORE leaves zombies behind on your system,
+# switch the comments between the two lines below
+# $SIG{CHLD} = \&deadbabe;
+$SIG{CHLD} = 'IGNORE';
# may need to do more - eg. if logging changes, close/reopen syslog/log file
# rethink - handler should be simple
@@ -240,15 +244,16 @@
sub main_loop() {
my ($inbuff, $mpid, $a);
- for (;;) {
- $a = accept(Client,Server);
+ while (($a = accept(Client,Server)) || $diedpid) {
do_log(3,"enter accept loop");
- report_children();
-
- # if the accept returned purely because of a caught
- # sigchld, then continue
- next unless $a;
+ # now we start the repeating loop...
+ if ($diedpid) {
+ $diedpid = 0;
+ # if the accept returned purely because of a caught sigchld
+ # then continue
+ next unless (defined($a));
+ }
if (!defined($mpid = fork)) {
shutdown Server, 2;
@@ -257,12 +262,12 @@
}
# if we're the parent, just go back to the accept loop
- if ($mpid) { # we are the parent
- $child_stime{$mpid} = time;
- next; # just go back to the accept loop
- }
- $SIG{CHLD} = undef;
- do_log(3,"forked off -- child [$$] running...");
+ next if ($mpid);
+
+ do_log(3,"forked off -- child running...");
+
+ $SIG{CHLD} = 'DEFAULT';
+ # reset sigchild - we don't want to mess up $? for the virus scanner
#
# Receive TEMPDIR/SENDER/RCPTS/LDA/LDAARGS from client
@@ -1326,9 +1331,6 @@
do_log(3,"removed pid file");
unlink("$socketname");
do_log(3,"removed socket");
- while (wait>=0) {}; # must wait for children (if still alive)
- # to get their status by the $SIG{CHLD} handler
- report_children();
}
($DO_SYSLOG eq "yes") ? closelog() : $log->close();
|