I just hit Ctrlc twice at my shell in an attempt to halt a process that is taking a long time to finish.
^C
was echoed twice, but the process just kept going.
Why didn't Ctrlc quit the process like it normally does?
I just hit Ctrlc twice at my shell in an attempt to halt a process that is taking a long time to finish.
^C
was echoed twice, but the process just kept going.
Why didn't Ctrlc quit the process like it normally does?
Processes can choose to:
trap '' INT
in a shell) or have their own handler for it that decides not to terminate (or fails to terminate in a timely fashion).stty int '^K'
in a shell)stty -isig
in a shell).Or, they can be uninterruptible, like when in a middle of a system call that can't be interrupted.
On Linux (with a relatively recent kernel), you can tell if a process is ignoring and/or handling SIGINT by looking at the output of
$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ: 0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000
SIGINT is 2. The second bit of SigIgn above is 1, which mean SIGINT is ignored.
You can automate that with:
$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ &&
$F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign
To check what the current intr
character is or if isig
is enabled for a given terminal:
$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig
(above the intr
character is ^C
(the character usually sent by your terminal (emulator) when pressing CTRL-C and input signals are not disabled.
$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig
(intr
character is ^K
and isig
is disabled for /dev/pts/1
).
For completeness, there are two other ways a process may do something to stop receiving SIGINTs though that's not something you would typically see.
Upon Ctrl+C, the SIGINT signal is sent to all the processes in the foreground process group of the terminal. It's usually the shell that place processes in process groups (mapped to shell jobs) and tell the terminal device which is the foreground one.
Now a process could:
Leave its process group. If it moves to another process group (any process group but the one that is the foreground one), then it will no longer receive the SIGINT upon Ctrl-C (nor the other keyboard-related signals like SIGTSTP, SIGQUIT). It could however get suspended if it tried to read (possibly write as well depending on the terminal device settings) from the terminal device (as background processes do).
As an example:
perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
could not be interruptible with Ctrl-C. Above perl
will try to join the process group whose ID is the same as its parent process ID. In general, there's no guarantee that there be such a process group with that id. But here, in the case of that perl
command run on its own at the prompt of an interactive shell, the ppid will be the shell's process and the shell will typically have been started in its own process group.
If the command is not already a process group leader (the leader of that foreground process group), then it starting a new process group would have the same effect.
For instance, depending on the shell,
$ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
PID PGID SID TTY TIME CMD
21435 21435 21435 pts/12 00:00:00 zsh
21441 21441 21435 pts/12 00:00:00 ps
21442 21441 21435 pts/12 00:00:00 perl
would have the same effect. ps
and perl
are started in the foreground process group, but on most shells, ps
would be the leader of that group (as seen in the ps
output above where the pgid of both ps
and perl
is the pid of ps
), so perl
can start its own process group.
Or it could change the foreground process group. Basically tell the tty device to send the SIGINT to some other process group upon Ctrl+C
perl -MPOSIX -e 'tcsetpgrp(0,getppid) or die$!; sleep 5'
There, perl
remains in the same process group but instead is telling the terminal device that the foreground process group is the one whose ID is the same as its parent process ID (see note above about that).
hdparm
or smartctl
on a defective hard disk that doesn't respond they will hang forever, and you can't kill them with CTRL+C. You can tell if a process is in uninterruptible sleep by looking at the stat column of ps aux
or at the S column of top
/htop
- D
means uninterruptible sleep. This isn't necessarily a bad thing though, it could just mean that the process is doing a lot of IO.
– Martin von Wittich
Sep 26 '13 at 21:56
kill -9 %
to kill it. Signal 9 cannot be ignored, nor can the suspend signal. The CTRL+Z keyboard sequence can be ignored in theory - but isn't in practice. – David Sainty Sep 26 '13 at 22:49perl -E '$SIG{TSTP} = sub { say "ha ha" }; sleep 1 while 1'
. You're probably thinking of SIGSTOP, which is a different signal. – derobert Sep 27 '13 at 15:50