diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2012-04-08 22:47:24 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2012-04-08 22:47:24 (GMT) |
commit | fa1d84107a22de80ee35a38e0c68ad988ebc66db (patch) | |
tree | 123903f9c68bd40f26a1cb08d896a770b7a61580 /Lib/SocketServer.py | |
parent | 088a874c7ff4e90d5b6efc16d37a53a57f368fea (diff) | |
download | cpython-fa1d84107a22de80ee35a38e0c68ad988ebc66db.zip cpython-fa1d84107a22de80ee35a38e0c68ad988ebc66db.tar.gz cpython-fa1d84107a22de80ee35a38e0c68ad988ebc66db.tar.bz2 |
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.
Diffstat (limited to 'Lib/SocketServer.py')
-rw-r--r-- | Lib/SocketServer.py | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py index 2ff3888..a44e137 100644 --- a/Lib/SocketServer.py +++ b/Lib/SocketServer.py @@ -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 |