Sorry, somehow the description got lost.

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

The sequence of events leading to that is:
- parent starts running
- parent creates SMTP listening socket
- parent forks a child; the child inherits the SMTP socket
- child creates an epoll set; the SMTP socket is added to that set
- parent creates its own epoll set; the config socket is added to that
  set
- child exits
- parent forks; the child inherits the SMTP socket and the parent's
  epoll socket
- this time, the child does not create its own epoll socket, but it uses
  the one inherited from parent; the SMTP socket is added to the epoll
  set
- because the epoll socket is shared, the parent may receive events for
  the SMTP socket; the Danga::Socket code sees that the SMTP socket is
  not tracked in the parent, so it closes it
- child exits
- parent forks; the SMTP socket was closed in parent, child cannot
  accept new SMTP connections

To prevent the above issue, an epoll socket should not be shared between
the parent and the child. I changed qpsmtpd-async to call
Danga::Socket->Reset in child, before doing any Danga::Socket work. This
would make the child use a newly created epoll socket. The child still
inherits the parent's epoll socket, but it does not use it.

The patch for Danga::Socket improves Reset() to close the epoll socket
too. This way, the parent's epoll socket will be closed in child.

The patch to qpsmtpd-async also closes the config socket in child. I
think the child does not need that socket.

Please review the patch and if it is OK, 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