elves / elvish

Powerful scripting language & versatile interactive shell
https://elv.sh/
BSD 2-Clause "Simplified" License
5.62k stars 300 forks source link

Ctrl-C in elvish kills Atom in background #364

Open muesli opened 7 years ago

muesli commented 7 years ago

Starting Atom from the terminal, it forks itself into the background. Pressing Ctrl-C in that terminal now will kill Atom.

xiaq commented 7 years ago

My theory: Atom only forks once without changing the process group. Most shells with job control will put processes it forks into a different process group, and Atom relies on that.

muesli commented 7 years ago

If I'm not mistaken, this is fixed now?

xiaq commented 4 years ago

No, this still reproduces.

krader1961 commented 4 years ago

FWIW, You don't need to use a command, like atom, that you might be unfamiliar with. Compile following C program. In fact, that program is useful because it makes it clear that @xiaq's hypothesis is correct. Run it, without & to background it, then press [ctrl-C] and you'll see that the signal is received by the "backgrounded" program. The square quotes are because elvish didn't background the program; it backgrounded itself via the fork() syscall.

You'll notice that when run from elvish its process group ID matches that of the elvish process ID. When run from a legacy shell like bash or ksh its process group ID will be for a process that no longer exists. Basically, when a legacy shell with full job control runs an external command it manipulates the process group leader for that command and the pgrp controlling the tty.

The solution for the moment is to explicitly background the command; e.g., atom &. That will put it in a different process group making it immune to the [ctrl-C].

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void sigint(int sig) {
        printf("WTF sig %d\n", sig);
}

int main() {
        signal(SIGINT, sigint);
        if (fork() == 0) {
                printf("pid %d  pgrp %d\n", getpid(), getpgrp());
                sleep(30);
        }
}
xiaq commented 4 years ago

@krader1961 thanks for the neat example.

I added a "maybe" tag as this can only be fixed by implementing (at least partially) job control, which I am not sure about at this moment.

Running atom & seems to be a reasonable workaround.