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 <no@no.no>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Andy Kipp <123@321.123>
This commit is contained in:
Andy Kipp 2025-01-13 12:27:29 +06:00 committed by GitHub
parent 5f62cd8b4e
commit 5be43ba7a8
Failed to generate hash of commit
4 changed files with 60 additions and 1 deletions

23
news/fix_cap_sub_bg.rst Normal file
View file

@ -0,0 +1,23 @@
**Added:**
* <news item>
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* Fixed hanging the command right after calling full capture subprocess (#5760).
**Security:**
* <news item>

View file

@ -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():

View file

@ -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)

View file

@ -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