From 4a985bffdbebbc82c517ac5e8c2cc88632f0894a Mon Sep 17 00:00:00 2001 From: Tadeu Manoel Date: Mon, 15 Jan 2024 17:51:12 -0300 Subject: [PATCH] Avoid I/O deadlock with conda `conda lock` may deadlock with a child `conda` process, it may be trying to read from `stdout` while `conda` is trying to write to `stderr` (blocked) Reading from `stdout` in a separate thread allows `stderr` to be consumed in the main thread. --- conda_lock/invoke_conda.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/conda_lock/invoke_conda.py b/conda_lock/invoke_conda.py index 04976cf11..f76142ccb 100644 --- a/conda_lock/invoke_conda.py +++ b/conda_lock/invoke_conda.py @@ -6,6 +6,7 @@ import shutil import subprocess import tempfile +import threading from distutils.version import LooseVersion from typing import IO, Dict, Iterator, List, Optional, Sequence, Union @@ -116,14 +117,21 @@ def _invoke_conda( ) as p: stdout = [] if p.stdout: - for line in _process_stdout(p.stdout): - logging.info(line) - stdout.append(line) + + def read_stdout() -> None: + assert p.stdout is not None + for line in _process_stdout(p.stdout): + logging.info(line) + stdout.append(line) + + stdout_thread = threading.Thread(target=read_stdout) + stdout_thread.start() stderr = [] if p.stderr: for line in p.stderr: stderr.append(line) logging.error(line.rstrip()) + stdout_thread.join() if check_call and p.returncode != 0: raise subprocess.CalledProcessError(