6

When running, for example, a& in bash, the terminal window closes, where I would expect a new process to start followed by an error message (similar to, for example, grep &).

What is causing this behavior? Is it intentional?

edit: as requested,

yuvalw@UX410UQK:~$ echo $-
himBH

I also tried opening another bash in bash to get additional output. My input is bash followed by a& and a few new lines:

yuvalw@UX410UQK:~$ bash
yuvalw@UX410UQK:~$ a&
[1] 15323
yuvalw@UX410UQK:~$ exit
yuvalw@UX410UQK:~$ a: command not found

yuvalw@UX410UQK:~$

here calling a& again will close the terminal window.

edit2: more echos

yuvalw@UX410UQK:~$ echo "$BASH_VERSION $SHELLOPTS $BASHOPTS"
4.3.48(1)-release braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath

trap:

yuvalw@UX410UQK:~$ trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU

type exit:

yuvalw@UX410UQK:~$ type exit
exit is a shell builtin

PROMPT_COMMAND (empty):

yuvalw@UX410UQK:~$ echo $PROMPT_COMMAND

PS1:

yuvalw@\UX410UQK:~$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$

edit 3: Opening a new terminal it doesn't seem like this happens, and I can run a& just fine, but after cding around for a bit the issue returns. In both cases the command_not_found_handle looks the same.

yuvalw@yuvalw-UX410UQK:~$ type command_not_found_handle

command_not_found_handle is a function
command_not_found_handle () 
{ 
    if [ -x /usr/lib/command-not-found ]; then
        /usr/lib/command-not-found -- "$1";
        return $?;
    else
        if [ -x /usr/share/command-not-found/command-not-found ]; then
            /usr/share/command-not-found/command-not-found -- "$1";
            return $?;
        else
            printf "%s: command not found\n" "$1" 1>&2;
            return 127;
        fi;
    fi
}
11
  • I don't get this behaviour at all. I just get the backgrounded pid [1] 3829, bash: a: command not found, then a new prompt.
    – Sparhawk
    Nov 19, 2017 at 9:22
  • Can you edit in the output of echo $-? Nov 19, 2017 at 9:23
  • 2
    What about the output of echo "$BASH_VERSION $SHELLOPTS $BASHOPTS" Nov 19, 2017 at 9:41
  • 1
    Still can't reproduce with same version, same settings. What about the output of trap and type exit? Nov 19, 2017 at 9:48
  • 1
    What's the output of type a command_not_found_handle? That's something I could reproduce with perl -MPOSIX -e '$SIG{TTOU} = "IGNORE"; tcsetpgrp(1,getpgrp) or die$!' &. That is with something that puts itself in foreground causing the shell to be in background and then fail to read from the terminal, causing it to exit with that exit message. Nov 19, 2017 at 15:32

1 Answer 1

14

That was a bug in bash, fixed in 4.4.

If you have the command_not_found_handle() hook defined (which is invoked when a command is not found), bash puts it in foreground even if the not found command was started in background.

Then, depending on timing, if the shell reads the command line from the tty device after the command_not_found_handle was put in foreground, that read() would return with an EIO error as happens when a background process reads from a terminal device and ignores the SIGTTIN signal.

bash would treat that as end of file on user input as if you had pressed Ctrl+D

One can reproduce the problem by doing:

$ command_not_found_handle() { sleep 20; }
$ a &
$ x

Even if the first read() succeeds because it's started before the command_not_found_handle is put in foreground, the second and subsequent reads after you press x will fail and cause the shell to exit.

With the default command_not_found_handle shipped on Ubuntu,

$ a & true &

Also causes the shell to exit as the SIGCHLD upon true returning interrupts the first read() and causes a second one to be started with the handler still running in foreground.

In the general case however, the bug seems unlikely to trigger as the shell also puts itself in foreground before writing its prompt, so the command_not_found_handle has to put itself in foreground (do the tcsetpgrp()) at the right moment (after the main shell process puts itself in foreground and before it starts reading from the tty device).

That was fixed in April 2015, with this commit (4/23 entry in CWRU.log) following a report to a related problem by Valentin Bajrami.

4
  • wow, that is a lot more obscure than I thought. Expected it to be something common.. Thank you very much for all the effort, was really informative to me! :)
    – Nescio
    Nov 20, 2017 at 10:01
  • @Nescio, it would be interesting to know why you can reproduce it consistently. What's your command_not_found_handle? (type command_not_found_handle). On which terminal to you see that? Do you see it regardless of which terminal emulator you're using? Are you in a setup where bash could end up being a child subreaper (container, systemd...)? What's the OS? Nov 20, 2017 at 12:26
  • I added some prints and some additional information to the question itself. I'm running Ubuntu 16.04 with the default terminal and bash, but honestly I'm pretty new to Linux so I am not sure if this is even a full answer to your question.
    – Nescio
    Nov 20, 2017 at 15:38
  • @Nescio. OK thanks, it's some comfort that you can't reproduce consistently. The main reason you can reproduce it more often that others is probably just chance (like your particular hardware puts the timing in that soft spot). Nov 20, 2017 at 15:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .