From 5be43ba7a8228b925ffea46822e9dc00ce737eff Mon Sep 17 00:00:00 2001 From: Andy Kipp Date: Mon, 13 Jan 2025 12:27:29 +0600 Subject: [PATCH] Fixed hanging the command right after calling full capture subprocess (#5769) * fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * test * test * test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * test --------- Co-authored-by: Andy Kipp Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Andy Kipp <123@321.123> --- news/fix_cap_sub_bg.rst | 23 +++++++++++++++++++++++ tests/test_integrations.py | 24 ++++++++++++++++++++++++ xonsh/procs/jobs.py | 6 +++++- xonsh/procs/specs.py | 8 ++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 news/fix_cap_sub_bg.rst diff --git a/news/fix_cap_sub_bg.rst b/news/fix_cap_sub_bg.rst new file mode 100644 index 000000000..ab5dc31fb --- /dev/null +++ b/news/fix_cap_sub_bg.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* Fixed hanging the command right after calling full capture subprocess (#5760). + +**Security:** + +* diff --git a/tests/test_integrations.py b/tests/test_integrations.py index b9dc4b5e9..74d8fac8d 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1387,6 +1387,30 @@ def test_alias_stability(): assert re.match(".*sleep.*sleep.*sleep.*", out, re.MULTILINE | re.DOTALL) +@skip_if_on_windows +@pytest.mark.flaky(reruns=3, reruns_delay=1) +def test_captured_subproc_is_not_affected_next_command(): + """Testing #5769.""" + stdin_cmd = ( + "t = __xonsh__.imp.time.time()\n" + "p = !(sleep 2)\n" + "print('OK_'+'TEST' if __xonsh__.imp.time.time() - t < 1 else 'FAIL_'+'TEST')\n" + "t = __xonsh__.imp.time.time()\n" + "echo 1\n" + "print('OK_'+'TEST' if __xonsh__.imp.time.time() - t < 1 else 'FAIL_'+'TEST')\n" + ) + out, err, ret = run_xonsh( + cmd=None, + stdin_cmd=stdin_cmd, + interactive=True, + single_command=False, + timeout=10, + ) + assert not re.match( + ".*FAIL_TEST.*", out, re.MULTILINE | re.DOTALL + ), "The second command after running captured subprocess shouldn't wait the end of the first one." + + @skip_if_on_windows @pytest.mark.flaky(reruns=3, reruns_delay=1) def test_spec_decorator_alias(): diff --git a/xonsh/procs/jobs.py b/xonsh/procs/jobs.py index 3c7433392..1e7b6a922 100644 --- a/xonsh/procs/jobs.py +++ b/xonsh/procs/jobs.py @@ -457,7 +457,11 @@ def add_job(info): info["status"] = info["status"] if "status" in info else "running" get_tasks().appendleft(num) get_jobs()[num] = info - if info["bg"] and XSH.env.get("XONSH_INTERACTIVE"): + if ( + not info["pipeline"].spec.captured == "object" + and info["bg"] + and XSH.env.get("XONSH_INTERACTIVE") + ): print_one_job(num) diff --git a/xonsh/procs/specs.py b/xonsh/procs/specs.py index 165c32b44..5960a5887 100644 --- a/xonsh/procs/specs.py +++ b/xonsh/procs/specs.py @@ -888,6 +888,14 @@ def _last_spec_update_captured(last: SubprocSpec): def _make_last_spec_captured(last: SubprocSpec): captured = last.captured callable_alias = callable(last.alias) + + if captured == "object": + """ + In full capture mode the subprocess is running in background in fact + and we don't need to wait for it in downstream code e.g. `jobs.wait_for_active_job`. + """ + last.background = True + # cannot used PTY pipes for aliases, for some dark reason, # and must use normal pipes instead. use_tty = xp.ON_POSIX and not callable_alias