This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Holger Freyther gerrit-no-reply at lists.osmocom.orgHolger Freyther has uploaded this change for review. ( https://gerrit.osmocom.org/13087 Change subject: process: Make killing processes non-sequential ...................................................................... process: Make killing processes non-sequential Change-Id: Icf1ac6774ea11880542012fd6c6ac73302bb74f5 --- M src/osmo_gsm_tester/process.py 1 file changed, 73 insertions(+), 3 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/87/13087/1 diff --git a/src/osmo_gsm_tester/process.py b/src/osmo_gsm_tester/process.py index 3050f83..bb13131 100644 --- a/src/osmo_gsm_tester/process.py +++ b/src/osmo_gsm_tester/process.py @@ -47,10 +47,75 @@ class ParallelTerminationStrategy(TerminationStrategy): """Processes will be terminated in parallel.""" - def terminate_all(self): - # TODO(zecke): Actually make this non-sequential. + def _prune_dead_processes(self, poll_first): + """Removes all dead processes from the list.""" + # Remove all processes that terminated! + self._processes = list(filter(lambda proc: proc.is_running(poll_first), self._processes)) + + def _build_process_map(self): + """Builds a mapping from pid to process.""" + self._process_map = {} for process in self._processes: - process.terminate() + pid = process.pid() + if pid is None: + continue + self._process_map[pid] = process + + def _poll_once(self): + """Polls for to be collected children once.""" + pid, result = os.waitpid(0, os.WNOHANG) + proc = self._process_map.get(pid) + # Did some other process die? + if pid == 0: + return False + if proc is None: + self.log("Unknown process with pid(%d) died." % pid) + return False + # Update the process state and forget about it + self.log("PID %d died..." % pid) + proc.result = result + proc.cleanup() + self._processes.remove(proc) + del self._process_map[pid] + return True + + def _poll_for_termination(self, time_to_wait_for_term=5): + """Waits for the termination of processes until timeout|all ended.""" + + wait_step = 0.001 + waited_time = 0 + while len(self._processes) > 0: + # Collect processes until there are none to be collected. + while True: + try: + if not self._poll_once(): + break + except ChildProcessError: + break + + # All processes died and we can return before sleeping + if len(self._processes) == 0: + break + waited_time += wait_step + # make wait_step approach 1.0 + wait_step = (1. + 5. * wait_step) / 6. + if waited_time >= time_to_wait_for_term: + break + time.sleep(wait_step) + + def terminate_all(self): + self.log("Scheduled to terminate %d processes." % len(self._processes)) + self._prune_dead_processes(True) + self._build_process_map() + + # Iterate through all signals. + for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGKILL]: + self.log("Starting to kill with %s" % sig.name) + for process in self._processes: + process.kill(sig) + if sig == signal.SIGKILL: + continue + self._poll_for_termination() class Process(log.Origin): @@ -145,6 +210,11 @@ def send_signal(self, sig): os.kill(self.process_obj.pid, sig) + def pid(self): + if self.process_obj is None: + return None + return self.process_obj.pid + def kill(self, sig): """Kills the process with the given signal and remembers it.""" self.log('Terminating (%s)' % sig.name) -- To view, visit https://gerrit.osmocom.org/13087 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-gsm-tester Gerrit-Branch: master Gerrit-MessageType: newchange Gerrit-Change-Id: Icf1ac6774ea11880542012fd6c6ac73302bb74f5 Gerrit-Change-Number: 13087 Gerrit-PatchSet: 1 Gerrit-Owner: Holger Freyther <holger at freyther.de> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190301/73705b14/attachment.htm>