Skip to content

Commit d4449b8

Browse files
authored
Clean shutdown on SIGINT, SIGHUP, SIGTERM, SIGQUIT (#908)
* sys.exit on SIGINT, SIGHUP, SIGTERM * Add todo for pending signal actions * SIGHUP is win only * Remove frametype signature as it causes lint issues and we are not using it anyways * SIGQUIT is not on Win
1 parent 99856a6 commit d4449b8

File tree

1 file changed

+30
-10
lines changed

1 file changed

+30
-10
lines changed

proxy/proxy.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import os
1212
import sys
1313
import time
14+
import signal
1415
import logging
1516

1617
from typing import List, Optional, Any
@@ -19,7 +20,7 @@
1920
from .core.event import EventManager
2021
from .common.utils import bytes_
2122
from .common.flag import FlagParser, flags
22-
from .common.constants import DEFAULT_LOCAL_EXECUTOR, DEFAULT_LOG_FILE, DEFAULT_LOG_FORMAT, DEFAULT_LOG_LEVEL
23+
from .common.constants import DEFAULT_LOCAL_EXECUTOR, DEFAULT_LOG_FILE, DEFAULT_LOG_FORMAT, DEFAULT_LOG_LEVEL, IS_WINDOWS
2324
from .common.constants import DEFAULT_OPEN_FILE_LIMIT, DEFAULT_PLUGINS, DEFAULT_VERSION
2425
from .common.constants import DEFAULT_ENABLE_DASHBOARD, DEFAULT_WORK_KLASS, DEFAULT_PID_FILE
2526

@@ -190,6 +191,7 @@ def setup(self) -> None:
190191
)
191192
self.acceptors.setup()
192193
# TODO: May be close listener fd as we don't need it now
194+
self._register_signals()
193195

194196
def shutdown(self) -> None:
195197
assert self.acceptors
@@ -204,6 +206,11 @@ def shutdown(self) -> None:
204206
self.listener.shutdown()
205207
self._delete_pid_file()
206208

209+
@property
210+
def remote_executors_enabled(self) -> bool:
211+
return self.flags.threadless and \
212+
not (self.flags.local_executor == int(DEFAULT_LOCAL_EXECUTOR))
213+
207214
def _write_pid_file(self) -> None:
208215
if self.flags.pid_file:
209216
with open(self.flags.pid_file, 'wb') as pid_file:
@@ -214,19 +221,32 @@ def _delete_pid_file(self) -> None:
214221
and os.path.exists(self.flags.pid_file):
215222
os.remove(self.flags.pid_file)
216223

217-
@property
218-
def remote_executors_enabled(self) -> bool:
219-
return self.flags.threadless \
220-
and not (self.flags.local_executor == int(DEFAULT_LOCAL_EXECUTOR))
224+
def _register_signals(self) -> None:
225+
# TODO: Handle SIGINFO, SIGUSR1, SIGUSR2
226+
signal.signal(signal.SIGINT, self._handle_exit_signal)
227+
signal.signal(signal.SIGTERM, self._handle_exit_signal)
228+
if not IS_WINDOWS:
229+
signal.signal(signal.SIGHUP, self._handle_exit_signal)
230+
# TODO: SIGQUIT is ideally meant for terminate with core dumps
231+
signal.signal(signal.SIGQUIT, self._handle_exit_signal)
232+
233+
@staticmethod
234+
def _handle_exit_signal(signum: int, _frame: Any) -> None:
235+
logger.info('Received signal %d' % signum)
236+
sys.exit(0)
237+
238+
239+
def sleep_loop() -> None:
240+
while True:
241+
try:
242+
time.sleep(1)
243+
except KeyboardInterrupt:
244+
break
221245

222246

223247
def main(**opts: Any) -> None:
224248
with Proxy(sys.argv[1:], **opts):
225-
while True:
226-
try:
227-
time.sleep(1)
228-
except KeyboardInterrupt:
229-
break
249+
sleep_loop()
230250

231251

232252
def entry_point() -> None:

0 commit comments

Comments
 (0)