Consider a machine with an s6-linux-init-maker-style setup, that also uses s6-rc in the stage2 and stage2_finish scripts. Longruns managed by s6-rc without a 'producer-for' file in their definition directory have their stdout and stderr redirected to the catch-all logger, and so do oneshots via the s6rc-oneshot-runner service. So if one wants to have a service output to the console instead (e.g. an early one in the boot process), its definition would have to do explicit redirections to /dev/console. But should the service also be turned into a session leader and set a controlling terminal, or only in special cases?
s6-supervise already runs its run script as a session leader, unless there's a ./nosetsid file in the service directory. (Not doing so would mean running all the services in the same session as the supervision tree, which can have bad consequences if there's a controlling terminal attached to the session.) Few services need a controlling terminal, and the ones that do, like for instance getty, usually allocate one themselves. Standard daemons that "run in the background" absolutely do not want one. A controlling terminal is the exception rather than the rule - so it's not the supervisor's job to provide one. If you want a service to output to the console, or to a terminal, then an explicit redirection is indeed the right way to do it, and you most likely have no use for a controlling terminal.
I thought that this was needed only in special cases, like in processes that end up spawning a shell, but I see other init systems sometimes do it automatically. For example, with nosh, a service configured to output to a terminal AND defined using a systemd unit file, when converted to a bundle directory (nosh's version of a service definition directory) with the converter tool, has a 'run' script that calls open-controlling-tty (nosh's chainloading utility to open a device as a controlling terminal). And sysvinit's code has setsid() and TIOCSCTTY ioctl() calls for child processes, depending on the 'runlevel' and 'action' fields of the corresponding line in /etc/inittab.
The setsid() is normal: init wants the daemons it supervises to run in their own session, that makes sense. s6-supervise does the same thing. I have no idea what the TIOCSCTTY is for, though. *What* device would you open as a controlling terminal in the general case? When init starts, /dev/console is explicitly *not* a terminal (which is why you can't have job control when using a shell as init). The only explanation I can see is that the supervision abilities of sysvinit are only used for gettys, and sysvinit opens /dev/ttyN, N being specified on the getty line in /etc/inittab. But it's a wild guess, and probably inaccurate. I have no idea what systemd does and I don't think it would be a good indicator of what *should* be done anyway. I suspect that the use of open-controlling-tty is there to mimic systemd's behaviour exactly; maybe Jonathan can shed more light on this. I'm not sure he's on the skaware ML though; this conversation would have a place on the supervision ML (I'll repost tomorrow night when I'm at home with my usual tools and more time).
What those two cases have in common is that the mechanism involved also unconditionally redirects stdin to a terminal device; in the nosh case, I'm not sure if because of a limitation of the unit file-to-bundle directory converter. But I don't know why the "controlling terminal maneuver" is done there, so I now wonder if s6-rc service definitions would also require it in more cases than I thought, instead of simple FD redirections.
I honestly believe the controlling terminal thing is a historical artefact that should not be there, because it is useless or even detrimental for most daemons, and supervised programs that do need a controlling terminal perform the maneuvers themselves. But it would be interesting indeed to hear confirmation, and in particular to have Jonathan's opinion about this. -- Laurent
