Repository: xonsh/xonsh

Issue:
ProcessLookupError: [Errno 3] No such process
``` pytb
$ echo $PS1
\[
\]\[\r\]\[\e[1;30;40m\]\[\e[1;37;40m\]\W\[\e[1;36;40m\]master%=\[\e[1;31;40m\]$\[\e[0m\]\[\]\[\]
Traceback (most recent call last):
  File "/Users/aaronmeurer/anaconda/lib/python3.4/site-packages/xonsh/shell.py", line 131, in default
    self.execer.exec(code, mode='single', glbs=self.ctx)  # no locals
  File "/Users/aaronmeurer/anaconda/lib/python3.4/site-packages/xonsh/execer.py", line 124, in exec
    return exec(code, glbs, locs)
  File "<xonsh-code>", line 1, in <module>
  File "/Users/aaronmeurer/anaconda/lib/python3.4/site-packages/xonsh/built_ins.py", line 551, in subproc_uncaptured
    return run_subproc(cmds, captured=False)
  File "/Users/aaronmeurer/anaconda/lib/python3.4/site-packages/xonsh/built_ins.py", line 520, in run_subproc
    'pgrp': os.getpgid(prev_proc.pid),
ProcessLookupError: [Errno 3] No such process
```



Discussion:
Thanks for reporting, @asmeurer!  I think that it is likely that this is related to the other issue you reported (#202).

I have been unable to replicate this behavior.  Is this something that always happens (regardless of what program you are trying to run), something that happens consistently when running a particular program, or something that just happens every once in a while?

Also, can you provide some information about your system?  For example, your operating system and xonsh version might be helpful, including how you installed xonsh (from pip, from current master, or from someplace else).

Mac OS X with iTerm 2 nightly. conda install -c scopatz xonsh. I haven't had time to use xonsh since this, so I can't say if it reproduces well or not. 

I'll try playing around with this tomorrow, on my mac.  Also, @asmeurer, what happens if you just do:

``` console
$ $PS1
# or
$ print($PS1)
```


Resolving patch:
diff --git a/xonsh/built_ins.py b/xonsh/built_ins.py
--- a/xonsh/built_ins.py
+++ b/xonsh/built_ins.py
@@ -4,7 +4,6 @@
 import os
 import re
 import sys
-import time
 import shlex
 import signal
 import locale
@@ -22,7 +21,7 @@
 from xonsh.inspectors import Inspector
 from xonsh.environ import default_env
 from xonsh.aliases import DEFAULT_ALIASES, bash_aliases
-from xonsh.jobs import print_one_job, get_next_job_number, wait_for_active_job
+from xonsh.jobs import add_job, wait_for_active_job
 from xonsh.jobs import ProcProxy
 
 ENV = None
@@ -508,21 +507,14 @@ def run_subproc(cmds, captured=True):
         prev_proc = proc
     for proc in procs[:-1]:
         proc.stdout.close()
-    num = get_next_job_number()
-    pids = [i.pid for i in procs]
     if not isinstance(prev_proc, ProcProxy):
-        builtins.__xonsh_active_job__ = num
-        builtins.__xonsh_all_jobs__[num] = {
+        add_job({
             'cmds': cmds,
-            'pids': pids,
+            'pids': [i.pid for i in procs],
             'obj': prev_proc,
-            'started': time.time(),
-            'pgrp': os.getpgid(prev_proc.pid),
-            'status': 'running',
             'bg': background
-        }
+        })
     if background:
-        print_one_job(num)
         return
     wait_for_active_job()
     if write_target is None:
diff --git a/xonsh/jobs.py b/xonsh/jobs.py
--- a/xonsh/jobs.py
+++ b/xonsh/jobs.py
@@ -3,6 +3,7 @@
 """
 import os
 import sys
+import time
 import signal
 import builtins
 from collections import namedtuple
@@ -56,7 +57,10 @@ def _give_terminal_to(pgid):
 
 def print_one_job(num):
     """Print a line describing job number ``num``."""
-    job = builtins.__xonsh_all_jobs__[num]
+    try:
+        job = builtins.__xonsh_all_jobs__[num]
+    except KeyError:
+        return
     act = '*' if num == builtins.__xonsh_active_job__ else ' '
     status = job['status']
     cmd = [' '.join(i) if isinstance(i, list) else i for i in job['cmds']]
@@ -76,6 +80,23 @@ def get_next_job_number():
     return i
 
 
+def add_job(info):
+    """
+    Add a new job to the jobs dictionary.
+    """
+    info['started'] = time.time()
+    info['status'] = 'running'
+    try:
+        info['pgrp'] = os.getpgid(info['obj'].pid)
+    except ProcessLookupError:
+        return
+    num = get_next_job_number()
+    builtins.__xonsh_all_jobs__[num] = info
+    builtins.__xonsh_active_job__ = num
+    if info['bg']:
+        print_one_job(num)
+
+
 def _default_sigint_handler(num, frame):
     raise KeyboardInterrupt
 


Test patch: