bash - terminating - How does Ctrl-C terminate a child process?

ctrl c not working linux (3)

CTRL+C is a map to the kill command. When you press them, kill sends a SIGINT signal, that's interrupts the process.

Kill :


I am trying to understand how CTRL+C terminates a child but not a parent process. I see this behavior in some script shells like bash where you can start some long-running process and then terminate it by entering CTRL-C and the control returns to the shell.

Could you explain how does it work and in particular why isn't the parent (shell) process terminated?

Does the shell have to do some special handling of CTRL+C event and if yes what exactly does it do?

Answer #1

First, read the Wikipedia article on the POSIX terminal interface all of the way through.

The SIGINT signal is generated by the terminal line discipline, and broadcast to all processes in the terminal's foreground process group. Your shell has already created a new process group for the command (or command pipeline) that you ran, and told the terminal that that process group is its (the terminal's) foreground process group. Every concurrent command pipeline has its own process group, and the foreground command pipeline is the one with the process group that the shell has programmed into the terminal as the terminal's foreground process group. Switching "jobs" between foreground and background is (some details aside) a matter of the shell telling the terminal which process group is now the foreground one.

The shell process itself is in yet another process group all of its own and so doesn't receive the signal when one of those process groups is in the foreground. It's that simple.

Answer #2

The terminal sends the INT (interrupt) signal to the process that is currently attached to the terminal. The program then receives it, and could choose to ignore it, or quit.

No process is necessarily being forcibly closed (although by default, if you don't handle sigint, I believe the behaviour is to call abort(), but I'd need to look that up).

Of course, the running process is isolated from the shell that launched it.

If you wanted the parent shell to go, launch your program with exec:

exec ./myprogram

That way, the parent shell is replaced by the child process