Issue #7978: socketserver now restarts the select() call when EINTR is returned.

This avoids crashing the server loop when a signal is received.
Patch by Jerzy Kozera.
This commit is contained in:
Antoine Pitrou 2012-04-09 00:47:24 +02:00
parent 317c8d257e
commit b0a9c66a49
4 changed files with 52 additions and 2 deletions

View file

@ -133,6 +133,7 @@ import socket
import select
import sys
import os
import errno
try:
import threading
except ImportError:
@ -147,6 +148,15 @@ if hasattr(socket, "AF_UNIX"):
"ThreadingUnixStreamServer",
"ThreadingUnixDatagramServer"])
def _eintr_retry(func, *args):
"""restart a system call interrupted by EINTR"""
while True:
try:
return func(*args)
except OSError as e:
if e.errno != errno.EINTR:
raise
class BaseServer:
"""Base class for server classes.
@ -222,7 +232,8 @@ class BaseServer:
# connecting to the socket to wake this up instead of
# polling. Polling reduces our responsiveness to a
# shutdown request and wastes cpu at all other times.
r, w, e = select.select([self], [], [], poll_interval)
r, w, e = _eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
self._handle_request_noblock()
finally:
@ -262,7 +273,7 @@ class BaseServer:
timeout = self.timeout
elif self.timeout is not None:
timeout = min(timeout, self.timeout)
fd_sets = select.select([self], [], [], timeout)
fd_sets = _eintr_retry(select.select, [self], [], [], timeout)
if not fd_sets[0]:
self.handle_timeout()
return