class ThreadedServer(object): def __init__(self, jobClass=None, jobArgs=(), **kw): self._jobClass = jobClass self._jobArgs = jobArgs self._threadPool = ThreadPool(**kw) def run(self, sock, timeout=1.0): """ The main loop. Pass a socket that is ready to accept() client connections. Return value will be True or False indiciating whether or not the loop was exited due to SIGHUP. """ # Set up signal handlers. self._keepGoing = True self._hupReceived = False # Might need to revisit this? if not sys.platform.startswith('win'): self._installSignalHandlers() # Set close-on-exec setCloseOnExec(sock) # Main loop. while self._keepGoing: try: r, w, e = select.select([sock], [], [], timeout) except select.error, e: if e[0] == errno.EINTR: continue raise if r: try: clientSock, addr = sock.accept() except socket.error, e: if e[0] in (errno.EINTR, errno.EAGAIN): continue raise setCloseOnExec(clientSock) if not self._isClientAllowed(addr): clientSock.close() continue # Hand off to Connection. conn = self._jobClass(clientSock, addr, *self._jobArgs) if not self._threadPool.addJob(conn, allowQueuing=False): # No thread left, immediately close the socket to hopefully # indicate to the web server that we're at our limit... # and to prevent having too many opened (and useless) # files. clientSock.close() self._mainloopPeriodic()
def __init__(self, jobClass=None, jobArgs=(), **kw): self._jobClass = jobClass self._jobArgs = jobArgs self._threadPool = ThreadPool(**kw)
class ThreadedServer(object): def __init__(self, jobClass=None, jobArgs=(), **kw): self._jobClass = jobClass self._jobArgs = jobArgs self._threadPool = ThreadPool(**kw) def run(self, sock, timeout=1.0): """ The main loop. Pass a socket that is ready to accept() client connections. Return value will be True or False indiciating whether or not the loop was exited due to SIGHUP. """ # Set up signal handlers. self._keepGoing = True self._hupReceived = False # Might need to revisit this? if not sys.platform.startswith('win'): self._installSignalHandlers() # Set close-on-exec setCloseOnExec(sock) # Main loop. while self._keepGoing: try: r, w, e = select.select([sock], [], [], timeout) except select.error as e: if e[0] == errno.EINTR: continue raise if r: try: clientSock, addr = sock.accept() except socket.error as e: if e[0] in (errno.EINTR, errno.EAGAIN): continue raise setCloseOnExec(clientSock) if not self._isClientAllowed(addr): clientSock.close() continue # Hand off to Connection. conn = self._jobClass(clientSock, addr, *self._jobArgs) if not self._threadPool.addJob(conn, allowQueuing=False): # No thread left, immediately close the socket to hopefully # indicate to the web server that we're at our limit... # and to prevent having too many opened (and useless) # files. clientSock.close() self._mainloopPeriodic() # Restore signal handlers. self._restoreSignalHandlers() # Return bool based on whether or not SIGHUP was received. return self._hupReceived def _mainloopPeriodic(self): """ Called with just about each iteration of the main loop. Meant to be overridden. """ pass def _exit(self, reload=False): """ Protected convenience method for subclasses to force an exit. Not really thread-safe, which is why it isn't public. """ if self._keepGoing: self._keepGoing = False self._hupReceived = reload def _isClientAllowed(self, addr): """Override to provide access control.""" return True # Signal handlers def _hupHandler(self, signum, frame): self._hupReceived = True self._keepGoing = False def _intHandler(self, signum, frame): self._keepGoing = False def _installSignalHandlers(self): supportedSignals = [signal.SIGINT, signal.SIGTERM] if hasattr(signal, 'SIGHUP'): supportedSignals.append(signal.SIGHUP) self._oldSIGs = [(x,signal.getsignal(x)) for x in supportedSignals] for sig in supportedSignals: if hasattr(signal, 'SIGHUP') and sig == signal.SIGHUP: signal.signal(sig, self._hupHandler) else: signal.signal(sig, self._intHandler) def _restoreSignalHandlers(self): for signum,handler in self._oldSIGs: signal.signal(signum, handler)
class ThreadedServer(object): def __init__(self, jobClass=None, jobArgs=(), **kw): self._jobClass = jobClass self._jobArgs = jobArgs self._threadPool = ThreadPool(**kw) def run(self, sock, timeout=1.0): """ The main loop. Pass a socket that is ready to accept() client connections. Return value will be True or False indiciating whether or not the loop was exited due to SIGHUP. """ # Set up signal handlers. self._keepGoing = True self._hupReceived = False # Might need to revisit this? if not sys.platform.startswith('win'): self._installSignalHandlers() # Set close-on-exec setCloseOnExec(sock) # Main loop. while self._keepGoing: try: r, w, e = select.select([sock], [], [], timeout) except select.error as e: if get_errno(e) == errno.EINTR: continue raise if r: try: clientSock, addr = sock.accept() except socket.error as e: if e.errno in (errno.EINTR, errno.EAGAIN): continue raise setCloseOnExec(clientSock) if not self._isClientAllowed(addr): clientSock.close() continue # Hand off to Connection. conn = self._jobClass(clientSock, addr, *self._jobArgs) if not self._threadPool.addJob(conn, allowQueuing=False): # No thread left, immediately close the socket to hopefully # indicate to the web server that we're at our limit... # and to prevent having too many opened (and useless) # files. clientSock.close() self._mainloopPeriodic() # Restore signal handlers. self._restoreSignalHandlers() # Return bool based on whether or not SIGHUP was received. return self._hupReceived def _mainloopPeriodic(self): """ Called with just about each iteration of the main loop. Meant to be overridden. """ pass def _exit(self, reload=False): """ Protected convenience method for subclasses to force an exit. Not really thread-safe, which is why it isn't public. """ if self._keepGoing: self._keepGoing = False self._hupReceived = reload def _isClientAllowed(self, addr): """Override to provide access control.""" return True # Signal handlers def _hupHandler(self, signum, frame): self._hupReceived = True self._keepGoing = False def _intHandler(self, signum, frame): self._keepGoing = False def _installSignalHandlers(self): supportedSignals = [signal.SIGINT, signal.SIGTERM] if hasattr(signal, 'SIGHUP'): supportedSignals.append(signal.SIGHUP) self._oldSIGs = [(x, signal.getsignal(x)) for x in supportedSignals] for sig in supportedSignals: if hasattr(signal, 'SIGHUP') and sig == signal.SIGHUP: signal.signal(sig, self._hupHandler) else: signal.signal(sig, self._intHandler) def _restoreSignalHandlers(self): for signum, handler in self._oldSIGs: signal.signal(signum, handler)