3

Please explain in detail (including tty related stuff) how is a sudo foreground process on a X terminal emulator actually killed on the Ctrl-C.

See the following example please:

$ sudo -u test_no_pw sleep 999 &                                    
[1] 16657                  
$ ps -o comm,pid,ppid,ruid,rgid,euid,egid,suid,sgid,sid,pgid -t
COMMAND           PID  PPID  RUID  RGID  EUID  EGID  SUID  SGID   SID  PGID
zsh             15254 15253  1000  1000  1000  1000  1000  1000 15254 15254
sudo            16657 15254     0  1000     0  1000     0  1000 15254 16657
sleep           16658 16657  1002  1002  1002  1002  1002  1002 15254 16657
ps              16660 15254  1000  1000  1000  1000  1000  1000 15254 16660
$ fg
[1]  + running    sudo -u test_no_pw sleep 999
^C
$ # it was killed

Before I interrupted the sudo I started the strace on it in another terminal:

# strace -p 16657
Process 16657 attached
restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL, si_value={int=809122100, ptr=0x54552036303a3934}} ---
[...SNIP...]

So the sender is SI_KERNEL, interesting. I've asked yesterday in IRC channels and Googled but got only hazy or incorrect answers. Most people said that terminal or shell will send the SINGINT to sudo but it seems to me that it cannot happpen according to kill(2):

For a process to have permission to send a signal it must either be privileged (under Linux: have the CAP_KILL capability), or the real or effective user ID of the sending process must equal the real or saved set-user-ID of the target process. In the case of SIGCONT it suffices when the sending and receiving processes belong to the same session. (Historically, the rules were different; see NOTES.)

I predict that it'll have something to do with sending some escape sequence with ASCII ETX (3) to a pseudo-terminal but I'm far from understanding it. (Why is does the signal originate from the kernel?)

Related but hazy/incorrect:

I'm mostly interested in how it works on Linux.

3

1 Answer 1

3

(This is an attempt to clarify and answer the question, but improvements and corrections are welcomed).

First, let's remove the sudo and the &+ fg from the scenario - as they are not affecting the station (I assumed you've used those mostly to get the PID). The question then becomes: 1) how does a process running in foreground of a terminal receives SIGINT; 2) what changes when the terminal is a pseudo-terminal using X11 (e.g. Xterm).

  1. The delivery of SIGINT (and SIGQUIT, SIGTSTP) are generated by the kernel controlling terminal driver, when it intercepts a CTRL-C character, which is why you see SI_KERNEL as the source. This happens regardless of X11 or pseudo-terminals. It is nicely illustrated in "Advanced Programming in the Unix Environment 2nd Edition (APUE2)", Figure 9.7, page 272 (I won't paste it here for copyright reasons, but I'm sure it can be found). It is further explained on page 275, section "9.8 Job Control". The relevant Linux kernel code is likely this: http://lingrok.org/xref/linux-linus/drivers/tty/n_tty.c#1254

  2. Now adding pseudo-terminals to the mix: the psudeo-terminal kernel code still uses the standard terminal code (mentioned above) - thus when the 'master' side of the PTY (the X-terminal) receives the X11 key-event of "CTRL-C", and sends it to the slave PTY, the character is detected by the kernel terminal drive, and it sends SIGINT to the foreground process group (sudo in your case). This is illustrated in APUE2, Figure 19.1 page 676.

In APUE2 page 706 there is a short paragraph "Signal Generation" mentioning that signals can be sent directly by the master PTY using ioctl(2) (e.g. http://lingrok.org/xref/linux-linus/drivers/tty/pty.c#482), however I believe this is not the case here.

Comments welcomed.

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