Call`abort_fun` on sigterm and restore previous handler to prevent erroneous termination of an already terminated process. Args: process: The process to terminate. abort_fun: Function taking two parameters: the process to terminate and an array with a boolean for storing if an a
(process, abort_fun, enabled)
| 33 | |
| 34 | @contextmanager |
| 35 | def handle_sigterm(process, abort_fun, enabled): |
| 36 | """Call`abort_fun` on sigterm and restore previous handler to prevent |
| 37 | erroneous termination of an already terminated process. |
| 38 | |
| 39 | Args: |
| 40 | process: The process to terminate. |
| 41 | abort_fun: Function taking two parameters: the process to terminate and |
| 42 | an array with a boolean for storing if an abort occured. |
| 43 | enabled: If False, this wrapper will be a no-op. |
| 44 | """ |
| 45 | # Variable to communicate with the signal handler. |
| 46 | abort_occured = [False] |
| 47 | |
| 48 | if enabled: |
| 49 | # TODO(https://crbug.com/v8/13113): There is a race condition on |
| 50 | # signal handler registration. In rare cases, the SIGTERM for stopping |
| 51 | # a worker might be caught right after a long running process has been |
| 52 | # started (or logic that starts it isn't interrupted), but before the |
| 53 | # registration of the abort_fun. In this case, process.communicate will |
| 54 | # block until the process is done. |
| 55 | previous = signal.getsignal(signal.SIGTERM) |
| 56 | def handler(signum, frame): |
| 57 | abort_fun(process, abort_occured) |
| 58 | if previous and callable(previous): |
| 59 | # Call default signal handler. If this command is called from a worker |
| 60 | # process, its signal handler will gracefully stop processing. |
| 61 | previous(signum, frame) |
| 62 | signal.signal(signal.SIGTERM, handler) |
| 63 | try: |
| 64 | yield |
| 65 | finally: |
| 66 | if enabled: |
| 67 | signal.signal(signal.SIGTERM, previous) |
| 68 | |
| 69 | if abort_occured[0]: |
| 70 | raise AbortException() |
| 71 | |
| 72 | |
| 73 | class BaseCommand(object): |
no test coverage detected