3

I like my background processes to freely write to the tty. stty -tostop is already the default in my zsh (I don't know why, perhaps because of OhMyzsh?):

❯ stty -a |rg tostop                                                                                                      
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt

But I still occasionally get my background processes suspended (this is not a consistent behavior, and I don't know how to reproduce it):

[1]  + 3479064 suspended (tty output)
HappyFace
  • 1,612

1 Answers1

4

A process can be sent that SIGTTOU signal (which causes that message), when it makes a TCSETSW or TCSETS ioctl() for instance (like when using the tcsetattr() libc function) to set the tty line discipline settings while not in the foreground process group of a terminal (like when invoked in background from an interactive shell), regardless of whether tostop is enabled or not (which only affects writes to the terminal).

$ stty echo &
[1] 290008
[1]  + suspended (tty output)  stty echo

See info libc SIGTTOU on a GNU system for details:

  • Macro: int SIGTTOU

    This is similar to SIGTTIN, but is generated when a process in a background job attempts to write to the terminal or set its modes. Again, the default action is to stop the process. SIGTTOU is only generated for an attempt to write to the terminal if the TOSTOP output mode is set

(emphasis mine)

I believe it's not the only ioctl() that may cause that. From a cursory look at the Linux kernel source code, looks like TCXONC (tcflow()), TCFLSH (tcflush()) should too.

  • Is there any way to stop this SIGTTOU from being sent, or at least ignore it in my zsh programs? Will trap -- '' SIGTTOU work? – HappyFace Jul 26 '20 at 20:15
  • I just tested trap -- '' TTOU SIGTTOU. It doesn't work, the process will still get suspended. – HappyFace Jul 26 '20 at 20:19
  • 1
    @HappyFace, the problem would seem to be that you're trying to run a command that is meant to interact with the tty in background. Maybe you can run it as cmd < /dev/null. What's the command that is causing you trouble? – Stéphane Chazelas Jul 26 '20 at 20:23
  • I don't really know what is the problem causer. (I tested trap using your own example of stty echo.) The setup is somewhat complex, and I have only once encountered this suspension error in it, though the error comes up in other contexts every few months. In that last time, a foreground sleep 30 was suspended, while there was another script running in the background, which seemed to have been killed (with no messages). I didn't understand the situation at all. I am hoping that I can sweep the problem under the rug by just ignoring SIGTTOU, as I don't care who does what with the TTY. – HappyFace Jul 26 '20 at 20:37
  • Interestingly, this link seems to indicate that ignoring SIGTTOU is possible in Python, and you can then change the terminal's configuration from the background. – HappyFace Jul 26 '20 at 20:39
  • 1
    Yes, zsh won't let you ignore the tty signals (TTIN, TTOU, TSTP, WINCH) even in non-interactive instances (which doesn't seem quite right to me), and zsh will even restore their default disposition on startup if they were previously ignored. – Stéphane Chazelas Jul 26 '20 at 20:40
  • I had a similar issue (csh shell and bash script, the script worked fine until I added stty -echoctl, it would then always suspend when launched into background ... &. I searched for and tried many tips (different shell, redirecting output e.g. ... &>/dev/null or ... | tee log, setting stty -tostop etc.), none worked. What finally fixed it was to add </dev/null to when launching the script (even though the script takes no console input) as suggested by @StéphaneChazelas in a comment above. Once the stdin was redirected, the script could be launched in the background again. – Petr Vepřek Apr 01 '23 at 20:34