Repository: xonsh/xonsh

Issue:
jobs fg: on ctrl+c, shell returns to prompt but task is still running on background
<!--- Provide a general summary of the issue in the Title above -->
<!--- If you have a question along the lines of "How do I do this Bash command in xonsh"
please first look over the Bash to Xonsh translation guide: https://xon.sh/bash_to_xsh.html
If you don't find an answer there, please do open an issue! -->

## xonfig

<details>

```
$ xonfig
+------------------+-----------------------------------+
| xonsh            | 0.11.0                            |
| Python           | 3.9.9                             |
| PLY              | 3.11                              |
| have readline    | True                              |
| prompt toolkit   | 3.0.22                            |
| shell type       | prompt_toolkit                    |
| history backend  | json                              |
| pygments         | 2.10.0                            |
| on posix         | True                              |
| on linux         | True                              |
| distro           | arch                              |
| on wsl           | False                             |
| on darwin        | False                             |
| on windows       | False                             |
| on cygwin        | False                             |
| on msys2         | False                             |
| is superuser     | False                             |
| default encoding | utf-8                             |
| xonsh encoding   | utf-8                             |
| encoding errors  | surrogateescape                   |
| on jupyter       | True                              |
| jupyter kernel   | None                              |
| xontrib          | []                                |
| RC file 1        | /home/fsinft/.config/xonsh/rc.xsh |
+------------------+-----------------------------------+
```

</details>

## Expected Behavior
<!--- Tell us what should happen -->
ctrl+c kills a task running on foreground
## Current Behavior
<!--- Tell us what happens instead of the expected behavior -->
on ctrl+c, shell returns to prompt but task is still running on background

## Steps to Reproduce
<!--- Please try to write out a minimal reproducible snippet to trigger the bug, it will help us fix it! -->
start a background task: `sleep 200 &`
bring it back to foreground using `fg`
send ctrl+c, and shell returns back to prompt
run `jobs` and see that the task was actually not killed and is running in background
![image](https://user-images.githubusercontent.com/48161833/145325988-d20477fa-0377-4246-bf33-4b9882a2c846.png)


## For community
⬇️  **Please click the 👍 reaction instead of leaving a `+1` or 👍  comment**



Discussion:

Resolving patch:
diff --git a/xonsh/procs/pipelines.py b/xonsh/procs/pipelines.py
--- a/xonsh/procs/pipelines.py
+++ b/xonsh/procs/pipelines.py
@@ -77,14 +77,14 @@ def safe_readable(handle):
     return status
 
 
-def update_fg_process_group(pipeline_group, background):
-    if background:
-        return False
+def update_process_group(pipeline_group, background):
     if not xp.ON_POSIX:
         return False
     env = XSH.env
     if not env.get("XONSH_INTERACTIVE"):
         return False
+    if background:
+        return True
     return xj.give_terminal_to(pipeline_group)
 
 
@@ -169,7 +169,7 @@ def __init__(self, specs):
                 and self.captured != "object"
             ):
                 pipeline_group = proc.pid
-                if update_fg_process_group(pipeline_group, background):
+                if update_process_group(pipeline_group, background):
                     self.term_pgid = pipeline_group
             self.procs.append(proc)
         self.proc = self.procs[-1]
diff --git a/xonsh/procs/specs.py b/xonsh/procs/specs.py
--- a/xonsh/procs/specs.py
+++ b/xonsh/procs/specs.py
@@ -918,14 +918,15 @@ def run_subproc(cmds, captured=False, envs=None):
     # now figure out what we should return
     if captured == "object":
         return command  # object can be returned even if backgrounding
+    elif captured == "hiddenobject":
+        if not background:
+            command.end()
+        return command
     elif background:
         return
     elif captured == "stdout":
         command.end()
         return command.output
-    elif captured == "hiddenobject":
-        command.end()
-        return command
     else:
         command.end()
         return


Test patch:
diff --git a/tests/procs/test_specs.py b/tests/procs/test_specs.py
--- a/tests/procs/test_specs.py
+++ b/tests/procs/test_specs.py
@@ -138,7 +138,7 @@ def test_capture_always(
     [
         ("object", False),
         ("stdout", True),
-        ("hiddenobject", True),
+        ("hiddenobject", False),
         (False, True),
     ],
 )
diff --git a/tests/test_pipelines.py b/tests/test_pipelines.py
--- a/tests/test_pipelines.py
+++ b/tests/test_pipelines.py
@@ -112,3 +112,10 @@ def test_raw_substitution(xonsh_execer):
 )
 def test_casting(cmdline, result, xonsh_execer):
     assert xonsh_execer.eval(f"{cmdline}") == result
+
+
+@skip_if_on_windows
+def test_background_pgid(xonsh_session, monkeypatch):
+    monkeypatch.setitem(xonsh_session.env, "XONSH_INTERACTIVE", True)
+    pipeline = xonsh_session.execer.eval("![echo hi &]")
+    assert pipeline.term_pgid is not None