From 3be7071238bc95dc06fcb7d554bd8381428348b0 Mon Sep 17 00:00:00 2001 From: sdotson Date: Fri, 24 Jun 2022 10:14:08 -0500 Subject: [PATCH 1/3] changes p.stdout.read to communicate() --- src/watts/fileutils.py | 21 ++++++++++----------- src/watts/plugin.py | 9 +++++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/watts/fileutils.py b/src/watts/fileutils.py index 97b4392d..c491a3b6 100644 --- a/src/watts/fileutils.py +++ b/src/watts/fileutils.py @@ -84,7 +84,7 @@ class tee_stderr(_TeeStream): _stream = "stderr" -def run(args): +def run(args, wait): """Function that mimics subprocess.run but actually writes to sys.stdout and sys.stderr (not the same as the underlying file descriptors) @@ -94,15 +94,14 @@ def run(args): p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) - while True: - select.select([p.stdout, p.stderr], [], []) + select.select([p.stdout, p.stderr], [], []) - stdout_data = p.stdout.read() - stderr_data = p.stderr.read() - if stdout_data: - sys.stdout.write(stdout_data) - if stderr_data: - sys.stderr.write(stderr_data) + try: + stdout_data, stderr_data = p.communicate(timeout=wait) + except subprocess.TimeoutExpired: + p.kill() + stdout_data, stderr_data = p.communicate() - if p.poll() is not None: - break + sys.stdout.write(stdout_data) + + sys.stderr.write(stderr_data) diff --git a/src/watts/plugin.py b/src/watts/plugin.py index f3881755..a00f41af 100644 --- a/src/watts/plugin.py +++ b/src/watts/plugin.py @@ -223,7 +223,8 @@ def postrun(self, params: Parameters, name: str, **kwargs) -> Results: return results_cls(params, name, time, inputs, outputs, **kwargs) def run(self, mpi_args: Optional[List[str]] = None, - extra_args: Optional[List[str]] = None): + extra_args: Optional[List[str]] = None, + wait: Optional[int] = 60): """Run plugin Parameters @@ -234,9 +235,13 @@ def run(self, mpi_args: Optional[List[str]] = None, extra_args Additional command-line arguments to append after the main command + wait + The time in seconds that `watts` will wait before terminating the process. + Default is 60 seconds. + """ if mpi_args is None: mpi_args = [] if extra_args is None: extra_args = [] - run_proc(mpi_args + self.execute_command + extra_args) + run_proc(mpi_args + self.execute_command + extra_args, wait) From 8864c723a75b85fd428700796b8114347de37559 Mon Sep 17 00:00:00 2001 From: sdotson Date: Fri, 24 Jun 2022 11:06:57 -0500 Subject: [PATCH 2/3] makes wait arg optional --- src/watts/fileutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/watts/fileutils.py b/src/watts/fileutils.py index c491a3b6..41bf4018 100644 --- a/src/watts/fileutils.py +++ b/src/watts/fileutils.py @@ -84,7 +84,7 @@ class tee_stderr(_TeeStream): _stream = "stderr" -def run(args, wait): +def run(args, wait=None): """Function that mimics subprocess.run but actually writes to sys.stdout and sys.stderr (not the same as the underlying file descriptors) From dd6647a9a69cdfcf10a7e44cfa649de827354a6b Mon Sep 17 00:00:00 2001 From: sdotson Date: Fri, 24 Jun 2022 14:57:42 -0500 Subject: [PATCH 3/3] checks if stdout_data before writing --- src/watts/fileutils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/watts/fileutils.py b/src/watts/fileutils.py index 41bf4018..4d52dee5 100644 --- a/src/watts/fileutils.py +++ b/src/watts/fileutils.py @@ -102,6 +102,8 @@ def run(args, wait=None): p.kill() stdout_data, stderr_data = p.communicate() - sys.stdout.write(stdout_data) + if stdout_data: + sys.stdout.write(stdout_data) - sys.stderr.write(stderr_data) + if stderr_data: + sys.stderr.write(stderr_data)