Here's an interesting behaviour that, as far as I can tell, is
completley undocumented, sightly consfusing but fairly logical. Your
program should receive a SIGTTOU when it is running in the background
and attempts to output to the terminal -- the idea being that you
shouldn't scramble the output by mixing it in while the shell is trying
to operate. Here's what the bash manual has to say
Background processes are those whose process group ID differs from the
terminal's; such processes are immune to key- board-generated signals.
Only foreground processes are allowed to read from or write to the
terminal. Background processes which attempt to read from (write to)
the terminal are sent a SIGTTIN (SIGTTOU) signal by the terminal
driver, which, unless caught, suspends the process.
So, consider the following short program, which writes some output and
catches any SIGTTOU's, with an optional flag to switch between canonical
and non-canonical mode.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h>
#include <unistd.h>
static void sig_ttou(int signo) {
printf("caught SIGTTOU\n");
signal(SIGTTOU, SIG_DFL);
kill(getpid(), SIGTTOU);
}
int main(int argc, char *argv[]) {
signal(SIGTTOU, sig_ttou);
if (argc != 1) {
struct termios tty;
printf("setting non-canoncial mode\n");
tcgetattr(fileno(stdout), &tty);
tty.c_lflag &= ~(ICANON);
tcsetattr(fileno(stdout), TCSANOW, &tty);
}
int i = 0;
while (1) {
printf(" *** %d ***\n", i++);
sleep(1);
}
}
This program ends up operating in an interesting manner.
Run in the background, canonical mode : no SIGTTOU and output gets
multiplexed with shell.
$ ./sigttou &
*** 0 ***
[1] 26171
$ *** 1 ***
*** 2 ***
*** 3 ***
Run in the background, non-canonical mode : SIGTTOU delivered
$ ./sigttou 1 &
[1] 26494
ianw@jj:/tmp$ setting non-canoncial mode
caught SIGTTOU
[1]+ Stopped ./sigttou 1
Run in the background, canonical mode, tostop set via stty : SIGTTOU
delivered, seemingly after a write proceeds
$ stty tostop
$ ./sigttou &
[2] 26531
ianw@jj:/tmp$ *** 0 ***
caught SIGTTOU
[2]+ Stopped ./sigttou
You can see a practical example of this by comparing the difference
between cat file & and more file &. The semantics make some
sense -- anything switching off canonical mode is like to be going to
really scramble your terminal, so it's good to stop it and let it's
terminal handling functions run. I'm not sure why canoncial background
is considered useful mixed in with your prompt, but someone, somewhere
must have decided it was so.
Update: upon further investigation, it is the switching of terminal
modes that invokes the SIGTTOU. To follow the logic through more, see
the various users of
tty_check_change
in the tty driver.