def _kill_listen_processes(namespace, force=False): """Identify all listening processes within the given namespace. Then, for each one, find its top parent with same cmdline (in case this process forked) and issue a SIGTERM to all of them. If force is True, then a SIGKILL will be issued to all parents and all their children. Also, this function returns the number of listening processes. """ pids = find_listen_pids_namespace(namespace) pids_to_kill = {utils.find_fork_top_parent(pid) for pid in pids} kill_signal = signal.SIGTERM if force: kill_signal = signal.SIGKILL children = [utils.find_child_pids(pid, True) for pid in pids_to_kill] pids_to_kill.update(itertools.chain.from_iterable(children)) for pid in pids_to_kill: # Throw a warning since this particular cleanup may need a specific # implementation in the right module. Ideally, netns_cleanup wouldn't # kill any processes as the responsible module should've killed them # before cleaning up the namespace LOG.warning(_LW("Killing (%(signal)d) [%(pid)s] %(cmdline)s"), {'signal': kill_signal, 'pid': pid, 'cmdline': ' '.join(utils.get_cmdline_from_pid(pid))[:80] }) try: utils.kill_process(pid, kill_signal, run_as_root=True) except Exception as ex: LOG.error(_LE('An error occurred while killing ' '[%(pid)s]: %(msg)s'), {'pid': pid, 'msg': ex}) return len(pids)
def _kill_listen_processes(namespace, force=False): """Identify all listening processes within the given namespace. Then, for each one, find its top parent with same cmdline (in case this process forked) and issue a SIGTERM to all of them. If force is True, then a SIGKILL will be issued to all parents and all their children. Also, this function returns the number of listening processes. """ pids = find_listen_pids_namespace(namespace) pids_to_kill = {utils.find_fork_top_parent(pid) for pid in pids} kill_signal = signal.SIGTERM if force: kill_signal = signal.SIGKILL children = [utils.find_child_pids(pid, True) for pid in pids_to_kill] pids_to_kill.update(itertools.chain.from_iterable(children)) for pid in pids_to_kill: # Throw a warning since this particular cleanup may need a specific # implementation in the right module. Ideally, netns_cleanup wouldn't # kill any processes as the responsible module should've killed them # before cleaning up the namespace LOG.warning("Killing (%(signal)d) [%(pid)s] %(cmdline)s", {'signal': kill_signal, 'pid': pid, 'cmdline': ' '.join(utils.get_cmdline_from_pid(pid))[:80] }) try: utils.kill_process(pid, kill_signal, run_as_root=True) except Exception as ex: LOG.error('An error occurred while killing ' '[%(pid)s]: %(msg)s', {'pid': pid, 'msg': ex}) return len(pids)
def _test_find_fork_top_parent( self, expected=_marker, find_parent_pid_retvals=None, pid_invoked_with_cmdline_retvals=None ): def _find_parent_pid(x): if find_parent_pid_retvals: return find_parent_pid_retvals.pop(0) pid_invoked_with_cmdline = {} if pid_invoked_with_cmdline_retvals: pid_invoked_with_cmdline["side_effect"] = pid_invoked_with_cmdline_retvals else: pid_invoked_with_cmdline["return_value"] = False with mock.patch.object(utils, "find_parent_pid", side_effect=_find_parent_pid), mock.patch.object( utils, "pid_invoked_with_cmdline", **pid_invoked_with_cmdline ): actual = utils.find_fork_top_parent(_marker) self.assertEqual(expected, actual)
def _test_find_fork_top_parent(self, expected=_marker, find_parent_pid_retvals=None, pid_invoked_with_cmdline_retvals=None): def _find_parent_pid(x): if find_parent_pid_retvals: return find_parent_pid_retvals.pop(0) pid_invoked_with_cmdline = {} if pid_invoked_with_cmdline_retvals: pid_invoked_with_cmdline['side_effect'] = ( pid_invoked_with_cmdline_retvals) else: pid_invoked_with_cmdline['return_value'] = False with mock.patch.object(utils, 'find_parent_pid', side_effect=_find_parent_pid), \ mock.patch.object(utils, 'pid_invoked_with_cmdline', **pid_invoked_with_cmdline): actual = utils.find_fork_top_parent(_marker) self.assertEqual(expected, actual)