This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author idsvandermolen
Recipients idsvandermolen
Date 2014-05-13.08:49:14
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1399970954.74.0.599178198558.issue21491@psf.upfronthosting.co.za>
In-reply-to
Content
collect_children routine in SocketServer.py contains two possible race conditions. First one is in while loop "while len(self.active_children) >= self.max_children:". If status of child is collected outside of Socket server (for example in signal handler or something), then the variable self.active_children will not match actual child processes and the os.waitpid(0, 0) within the while loop will raise os.error, errno=10 (ECHILD) "No Child Processes". self.active_children should be emptied in this case, otherwise you'll end up with an endless loop comsuming 100% CPU (as happened to us).

The second possible race condition is below in the collect_children routine in the "for child in self.active_children" which contains a statement self.active_children.remove(pid) which would modify the iterator. I do not now about python 2.7, but before this would result in "incorrect iteration".
Original code:
        for child in self.active_children:
            try:
                pid, status = os.waitpid(child, os.WNOHANG)
            except os.error:
                pid = None
            if not pid: continue
            try:
                self.active_children.remove(pid)
            except ValueError, e:
                raise ValueError('%s. x=%d and list=%r' % (e.message, pid, self.active_children))

Fixed code:
        to_remove = []
        for child in self.active_children:
            try:
                pid, status = os.waitpid(child, os.WNOHANG)
            except os.error:
                pid = None
            if not pid: continue
            to_remove.append(pid)

        for pid in to_remove:
            try:
                self.active_children.remove(pid)
            except ValueError, e:
                raise ValueError('%s. x=%d and list=%r' % (e.message, pid, self.active_children))
History
Date User Action Args
2014-05-13 08:49:14idsvandermolensetrecipients: + idsvandermolen
2014-05-13 08:49:14idsvandermolensetmessageid: <1399970954.74.0.599178198558.issue21491@psf.upfronthosting.co.za>
2014-05-13 08:49:14idsvandermolenlinkissue21491 messages
2014-05-13 08:49:14idsvandermolencreate