Example #1
0
    async def _signal_and_wait(self, signum):
        """
        Send a SIGTERM or SIGKILL to the child process & reap it.

        - Send the signal to the process
        - Make sure we don't restart it when it stops
        - Wait for it to stop
        - Remove signal handler for it after we are done.
        """

        # Aquire lock to modify process sate
        async with self._proc_lock:
            # Don't yield control between sending signal & calling wait
            # This way, we don't end up in a call to _restart_process_if_needed
            # and possibly restarting. We also set _killed, just to be sure.
            self.proc.send_signal(signum)
            self._killed = True

            # We cancel the restart watcher & wait for the process to finish,
            # since we return only after the process has been reaped
            self._restart_process_future.cancel()
            await self.proc.wait()
            self.running = False
            # Remove signal handler *after* the process is done
            atexitasync.remove_handler(self._handle_signal)
Example #2
0
    async def _restart_process_if_needed(self):
        """
        Watch for process to exit & restart it if needed.

        This is a long running task that keeps running until the process
        exits. If we restart the process, `start()` sets this up again.
        """
        retcode = await self.proc.wait()
        # FIXME: Do we need to aquire a lock somewhere in this method?
        atexitasync.remove_handler(self._handle_signal)
        self._debug_log('exited', '{} exited with code {}', {'code': retcode},
                        self.name, retcode)
        self.running = False
        if (not self._killed) and (self.always_restart or retcode != 0):
            await self.start()