18

My current understanding of signals from keyboard in terminal is (based largely on trying to map my observations to what can be found on google) following:

  • User presses C-c
  • This is sent to input buffer of terminal as a byte which is computed by clearing 2 leftmost bits from 7 bit ascii value of c

After this it starts to be really foggy, because the configuration what input means what signal is done in terminal (stty). I suppose it means that the terminal itself is sending the signal to the process. But I also though that terminal does not know about application that is reading it.

How does sending a signal by keyboard in terminal work from end to end?

1 Answers1

36

Pressing C while Ctrl is pressed sends a keypress followed by keyrelease X11 event to the terminal emulator.

Upon that event (generally the keypress one), the terminal emulator writes the 0x3 byte (^C) to its file descriptor on the master side of the pseudo-tty device.

If the isig termios setting of the device is on and if the intr setting is set to that 0x3 byte, then the kernel sends the SIGINT signal to all the members of the foreground process group of the terminal device (another attribute stored in the pty device). In that case, the 0x3 byte will not be available for reading on the slave side of the pty.

It's usually interactive shells that create process groups (with setpgid()) for shell jobs, and decide which one to put in foreground (with tcsetpgrp() to set that attribute of the pty device) or not.

For instance when you run at the prompt of an interactive shell:

foo | bar

The shell starts a new process groups with two processes (in which it executes foo and bar after having connected their stdin/out with a pipe) and puts that group in foreground. Both processes would receive the SIGINT if you pressed Ctrl-C.

In:

foo | bar &

Same but the process group is not put in foreground (and the shell also doesn't wait for it so you can enter other commands). Those processes would not get the SIGINT upon Ctrl-C but could be suspended if they try to read from the tty device.

More reading at: What are the responsibilities of each Pseudo-Terminal (PTY) component (software, master side, slave side)?

  • 2
    Thanks for the rich answer. I'll try to rephrase the core of the answer to be sure that I understand it: The signal is sent by the kernel, who is monitoring the tty device itself for input that's configured in the device attributes (by whoever wants to configure it) and the kernel sends it to process group which is also configured in the device attributes (mainly by shell as one of the duties of a session leader). I hope this is correct. – calavera.info Mar 10 '17 at 10:42
  • 1
    @calavera.info, yes that's correct. In the case of a real terminal at the end of a serial cable, the kernel is looking for that 0x3 byte coming from the wire. For a pseudo-terminal, the master side replaces the wire. And the kernel is looking for that 0x3 byte in the bytes sent there by the terminal emulator. See also the edit with a link to another Q&A with more details (like the fact that that kernel processing is part of a modular design which is done when the device is used as a "terminal" device (terminal line discipline). – Stéphane Chazelas Mar 10 '17 at 10:48
  • Didn't the question say terminal, rather than terminal emulator? I don't suppose it makes much difference, given that the emulator's function is to act as much like a terminal as possible... – Toby Speight Mar 10 '17 at 15:08
  • 2
    @Toby, yes, since hardly anybody uses real terminal these days, I assumed the OP meant terminal emulators (many of them are called "terminal"). See also my comment above yours and the linked Q&A for more details. – Stéphane Chazelas Mar 10 '17 at 15:23
  • 1
    @TobySpeight Yes, I was asking about a terminal because I'm dealing with the real terminal over serial line, but the answer and following comments was completely valid for both cases. – calavera.info Mar 10 '17 at 15:59