title: What should interactive shells do in orphaned process groups?
body: <p>The short question is, what should a shell do if it is in an orphaned process group that doesn't own the tty? But I recommend reading the long question because it's amusing.</p>
  
  <p>Here is a fun and exciting way to turn your laptop into a portable space heater, using your favorite shell (unless you're one of those tcsh weirdos):</p>
  
  <pre><code>#include &lt;unistd.h&gt;   
  int main(void) {
      if (fork() == 0) {
          execl("/bin/bash", "/bin/bash", NULL);
      }
      return 0;
  }
  </code></pre>
  
  <p>This causes bash to peg the CPU at 100%. zsh and fish do the same, while ksh and tcsh mumble something about job control and then keel over, which is a bit better, but not much. Oh, and it's a platform agnostic offender: OS X and Linux are both affected.</p>
  
  <p>My (potentially wrong) explanation is as follows: the child shell detects it is not in the foreground: <code>tcgetpgrp(0) != getpgrp()</code>. Therefore it tries to stop itself: <code>killpg(getpgrp(), SIGTTIN)</code>. But its process group is orphaned, because its parent (the C program) was the leader and died, and SIGTTIN sent to an orphaned process group is just dropped (otherwise nothing could start it again). Therefore, the child shell is not stopped, but it's still in the background, so it does it all again, right away. Rinse and repeat.</p>
  
  <p>My question is, how can a command line shell detect this scenario, and what is the right thing for it to do? My thought is that the shell tries to <code>read</code> from stdin, and just exits if read gives it EIO.</p>
  
  <p>Thanks for your thoughts!</p>
  
  <p><em>Edit</em>: I tried doing a zero-length read() on /dev/tty, and that succeeded, which is bad. To get the EIO, I actually have to be prepared to read some data off of /dev/tty.</p>
  
  <p><em>Edit</em>: Another thought I had was to <code>kill(getpgrp(), 0)</code>. If the process group is orphaned, then I believe this will always fail. However, it may also fail because I don't have permission to signal the session leader.</p>
  
  <p><em>Edit</em>: For anyone finding this later, what I ended up doing is described at <a href="https://github.com/fish-shell/fish-shell/issues/422" rel="noreferrer">https://github.com/fish-shell/fish-shell/issues/422</a> . Also, how's the future?</p>