The well behaved Unix program and job control signals
The TTY demystified (which I've commented on before) has some things to say about the SIGTT* job control signals. In the process it says something about how they are and should be handled that I think is dangerously misleading.
Specifically, contrary to what The TTY demystified says, you
shouldn't assume that the shell saves and restores TTY modes for
you when your program is suspended and restored. A well behaved
Unix program that changes the TTY modes will remember and restore
the original modes when it gets
SIGTTOU, and then
re-set them to what it needs when it gets
SIGCONT. Note that a
well behaved program may need to do much more than just save and
restore TTY modes; one of the reasons that programs get sent the
SIGTT* signals (instead of just being abruptly suspended) is so
that they can do things like reset the terminal state away from
whatever peculiar colours and other settings they've placed it into.
(This is where the alternate screen plague kicks in.)
These days I think that basically all surviving shells (at least ones with job control) do save and restore TTY modes for you, because sadly this is basic self defense on part of the shell. However, they generally don't reset the terminal state (partly because they often have no idea what state you've put it into).
(This has implications for how your program should handle
that'll take another entry.)
The article also asks (after discussing ^S/^Q flow control):
I don't know why the designers of UNIX had to go all the way to invent
SIGTTINinstead of relying on blocking I/O, but my best guess is that the TTY driver, being in charge of job control, was designed to monitor and manipulate whole jobs; never the individual processes within them.
The straightforward answer is that the SIGTT* signals are designed to
give your program a chance to react to being suspended. That's why
you can catch them at all, unlike
SIGSTOP. If the TTY driver simply
blocked your process from doing further TTY IO (or just sent you a
SIGSTOP), your program couldn't clean up any special state it had set
and doing this would be entirely on the shoulders of the shell (which
cannot do it as well as your program can in many situations).
Sidebar: why the shell has trouble restoring the terminal state
At one level and in theory, restoring the terminal state is simple; the shell can just send the terminfo state reset sequence. However there are two problems with this. The first is the general problem of interrupting an operation in the middle; if the program was abruptly suspended partway through sending the terminal an escape sequence, the terminal may be in a mode where it will interpret part of your reset sequence as part of the incomplete escape sequence.
The second problem is that sometimes, part of 'resetting' things is
program dependent. The big example is where you should (re)position the
cursor. The cursor may have been put in an arbitrary and potentially
strange position and thus needs to be repositioned somewhere useful,
or it might be in a perfectly sensible location already and you should
leave it alone. The first case is typical of a full screen program like
vi (where the cursor will usually be repositioned to the bottom of
the screen); the second case is typical of a program that just uses
readline. The shell generally can't know which program is which.