summaryrefslogtreecommitdiff
path: root/wsgitools/scgi/forkpool.py
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2019-03-10 17:49:00 +0100
committerHelmut Grohne <helmut@subdivi.de>2019-03-10 17:49:00 +0100
commit44bdfe2a595ce06dfda3d00ee0cf65e565c3cbea (patch)
tree281f410fd9ac2bcc7ccb7b326dcb9a034dad4eb0 /wsgitools/scgi/forkpool.py
parenta10a7217cf963731e2566c1aa7cb6f7b96152b59 (diff)
downloadwsgitools-44bdfe2a595ce06dfda3d00ee0cf65e565c3cbea.tar.gz
scgi.forkpool: fix SIGTERM handler in the presence of PEP475
Since PEP475 or Python 3.5, select retries an interrupted system call. However, we were relying on the previous behaviour. Thus we must interrupt select using some other measure. Another socketpair is created and the signal handler transfers a byte on shutdown.
Diffstat (limited to 'wsgitools/scgi/forkpool.py')
-rw-r--r--wsgitools/scgi/forkpool.py15
1 files changed, 13 insertions, 2 deletions
diff --git a/wsgitools/scgi/forkpool.py b/wsgitools/scgi/forkpool.py
index b2bedcc..20943fc 100644
--- a/wsgitools/scgi/forkpool.py
+++ b/wsgitools/scgi/forkpool.py
@@ -236,6 +236,7 @@ class SCGIServer(object):
self.cpulimit = cpulimit
self.timelimit = timelimit
self.server = None # becomes a socket
+ self.sigpipe = None # becomes a pair socketpair endpoints
# maps filedescriptors to WorkerStates
self.workers = {}
self.running = False
@@ -262,6 +263,7 @@ class SCGIServer(object):
self.server.listen(5)
else:
self.server = self.reusesocket
+ self.sigpipe = socket.socketpair()
self.running = True
while self.running:
while (len(self.workers) < self.minworkers or # less than min
@@ -269,13 +271,18 @@ class SCGIServer(object):
not len([w for w in # no inactive
self.workers.values() if w.state == 0]))):
self.spawnworker()
+ rs = list(self.workers.keys())
+ rs.append(self.sigpipe[0])
try:
- rs, _, _ = select.select(self.workers.keys(), [], [])
+ rs, _, _ = select.select(rs, [], [])
except select.error as e:
if e[0] != errno.EINTR:
raise
rs = []
for s in rs:
+ if s == self.sigpipe[0]:
+ self.sigpipe[0].recv(1)
+ continue
try:
data = self.workers[s].sock.recv(1)
except socket.error:
@@ -297,6 +304,9 @@ class SCGIServer(object):
if self.reusesocket is None:
self.server.close()
self.server = None
+ self.sigpipe[0].close()
+ self.sigpipe[1].close()
+ self.sigpipe = None
self.killworkers()
def killworkers(self, sig=signal.SIGTERM):
@@ -321,8 +331,9 @@ class SCGIServer(object):
"""
if self.ischild:
sys.exit()
- else:
+ elif self.running:
self.running = False
+ self.sigpipe[1].send(b' ')
def sigxcpuhandler(self, sig=None, stackframe=None):
"""