diff options
author | Helmut Grohne <helmut@subdivi.de> | 2019-03-10 17:49:00 +0100 |
---|---|---|
committer | Helmut Grohne <helmut@subdivi.de> | 2019-03-10 17:49:00 +0100 |
commit | 44bdfe2a595ce06dfda3d00ee0cf65e565c3cbea (patch) | |
tree | 281f410fd9ac2bcc7ccb7b326dcb9a034dad4eb0 /wsgitools/scgi/forkpool.py | |
parent | a10a7217cf963731e2566c1aa7cb6f7b96152b59 (diff) | |
download | wsgitools-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.py | 15 |
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): """ |