I found that qpsmtpd-async may stop accepting new SMTP connections if a
child server dies and a new child is created.

The sequence of events leading to a closed SMTP socket was:
- parent creates the SMTP listening socket
- parent forks a child; the child inherits the SMTP socket
- child creates epoll set; child adds the SMTP socket to that set
- parent creates its own epoll set, for the config port
- child exits
- parent spawns new child; the new child inherits parent's epoll set and
  this time it does not create its own epoll set but will use the
  inherited one; the SMTP socket is added to the epoll set
- the shared epoll set will make parent receive notifications for the
  SMTP socket; Danga::Socket, as a defense, will close the SMTP socket
  because it is not tracked in parent

To prevent the above issue an epoll socket should not be shared between
the parent and the child, each one should have its own epoll socket.

I changed qpsmtpd-async to call Danga::Socket->Reset() in the child,
before starting the child's event loop. With Danga::Socket 1.58 this
would create a new epoll socket in the child. The child still inherits
the parent's epoll socket, but does not use it. I have a patch for
Danga::Socket too, to close the epoll socket inside Reset(). If this
patch would get applied, then parent and child will share no more epoll
sockets.

In the patch for qpsmtpd-async I also close the config socket in the
child, I think it makes sense.

Please review and if it looks apply, please apply it.


Thank you,
Radu Greab


=== qpsmtpd-async
==================================================================
--- qpsmtpd-async       (revision 111)
+++ qpsmtpd-async       (local)
@@ -163,6 +163,8 @@
     $SIG{PIPE} = 'IGNORE';
     $SIG{HUP}  = 'IGNORE';
     
+    close $CONFIG_SERVER;
+    Qpsmtpd::PollServer->Reset;
     Qpsmtpd::PollServer->OtherFds(
         fileno($reader) => sub { command_handler($reader) },
         fileno($SERVER) => \&accept_handler,
--- /home/radu/.cpan/build/Danga-Socket-1.58/lib/Danga/Socket.pm.orig   
2008-01-21 21:34:57.000000000 +0200
+++ /home/radu/.cpan/build/Danga-Socket-1.58/lib/Danga/Socket.pm        
2008-03-09 19:29:35.000000000 +0200
@@ -185,6 +185,9 @@
     %PLCMap = ();
     $DoneInit = 0;
 
+    POSIX::close($Epoll)  if defined $Epoll  && $Epoll  >= 0;
+    POSIX::close($KQueue) if defined $KQueue && $KQueue >= 0;
+ 
     *EventLoop = *FirstTimeEventLoop;
 }
 

Reply via email to