1111import os
1212import sys
1313import time
14+ import signal
1415import logging
1516
1617from typing import List , Optional , Any
1920from .core .event import EventManager
2021from .common .utils import bytes_
2122from .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
2324from .common .constants import DEFAULT_OPEN_FILE_LIMIT , DEFAULT_PLUGINS , DEFAULT_VERSION
2425from .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
223247def 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
232252def entry_point () -> None :
0 commit comments