From 445d5ec7201a86458182f89b1b26417341dadf4f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 6 Mar 2022 21:09:46 +0100 Subject: [PATCH] propagate signals to running commands otherwise, we have long running processes when GitLab terminates jobs in a pipeline --- python/damask/util.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/python/damask/util.py b/python/damask/util.py index 880e815e8..7408bdfe4 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -6,9 +6,10 @@ import os import subprocess import shlex import re +import signal import fractions from collections import abc -from functools import reduce +from functools import reduce, partial from typing import Callable, Union, Iterable, Sequence, Dict, List, Tuple, Literal, Any, Collection from pathlib import Path @@ -174,21 +175,35 @@ def run(cmd: str, Output of the executed command. """ + def pass_signal(sig,_,proc,default): + proc.send_signal(sig) + signal.signal(sig,default) + signal.raise_signal(sig) + + signals = [signal.SIGINT,signal.SIGTERM] + print(f"running '{cmd}' in '{wd}'") - process = subprocess.run(shlex.split(cmd), + process = subprocess.Popen(shlex.split(cmd), stdout = subprocess.PIPE, stderr = subprocess.PIPE, env = os.environ if env is None else env, cwd = wd, - encoding = 'utf-8', - timeout = timeout) + encoding = 'utf-8') + # ensure that process is terminated (https://stackoverflow.com/questions/22916783) + sig_states = [signal.signal(sig,partial(pass_signal,proc=process,default=signal.getsignal(sig))) for sig in signals] + + try: + stdout,stderr = process.communicate(timeout=timeout) + finally: + for sig,state in zip(signals,sig_states): + signal.signal(sig,state) if process.returncode != 0: - print(process.stdout) - print(process.stderr) + print(stdout) + print(stderr) raise RuntimeError(f"'{cmd}' failed with returncode {process.returncode}") - return process.stdout, process.stderr + return stdout, stderr execute = run