pages tagged setsidyakkinghttp://yakking.branchable.com/tags/setsid/yakkingikiwiki2017-04-26T12:00:14ZIs your process running 3 - UNIX sessionshttp://yakking.branchable.com/posts/procrun-3-unix-sessions/Richard Maw2017-04-26T12:00:14Z2017-04-26T12:00:07Z
<p>We previously discussed issues with using PIDfiles.</p>
<p>One issue we encountered was that we need a way to handle multiple processes.</p>
<h1>Process groups</h1>
<p>If you've ever started a program in the background in a shell
you might have noticed it gave you a "Job ID" to refer to it
rather than a process ID.</p>
<p>This is not just to give you a memorable number for each task,
but because jobs may contain multiple processes,
which is how a pipeline of multiple processes may be a single job.</p>
<p>This is accomplished in Linux and traditional UNIXes
with the <a href="http://man7.org/linux/man-pages/man2/setpgrp.2.html">setpgrp(2)</a> system call
which assigns a new process group to a process
which will be inherited by its subprocesses.</p>
<p>This entire process group may be killed
by passing the negation of the process group ID
to the <a href="http://man7.org/linux/man-pages/man2/kill.2.html">kill(2)</a> system call.</p>
<p>A process may only be part of one process group though,
so if you have processes that may call <a href="http://man7.org/linux/man-pages/man2/setpgrp.2.html">setpgrp(2)</a> themselves
then it is not possible to use process groups
to manage terminating a whole process tree of a service.</p>
<h1>UNIX Sessions</h1>
<p>You may be wondering how anything can possibly work
if you can't use process groups to track a user's processes.</p>
<p>The answer to this is that UNIX has a concept of sessions.</p>
<p>Every process is a part of a session,
and each session has a "controlling TTY",
which can be accessed via <code>/dev/tty</code>.</p>
<p>When a process creates a new session with <a href="http://man7.org/linux/man-pages/man2/setsid.2.html">setsid(2)</a>
it becomes the session leader.</p>
<p>If the session leader process is terminated
then the entire session receives the <code>SIGHUP</code> signal,
which by default terminates the process.</p>
<p>The controlling tty was traditionally a <a href="https://en.wikipedia.org/wiki/Virtual_terminal">virtual terminal</a>
which emulates the old teletype terminals on modern computers.
<a href="https://en.wikipedia.org/wiki/Xterm">Terminal windows in graphical interfaces</a> use <a href="https://en.wikipedia.org/wiki/Pseudoterminal">pseudo terminals</a>,
which could be used to use sessions
for grouping processes that don't belong to a device.</p>
<p>This is typically done by <a href="https://en.wikipedia.org/wiki/Getty_(Unix)">getty</a> and <a href="http://man7.org/linux/man-pages/man1/login.1.html">login(1)</a>, <a href="https://en.wikipedia.org/wiki/Xterm">terminal emulator</a>
or <a href="https://linux.die.net/man/8/sshd">sshd</a>,
which also update <a href="http://man7.org/linux/man-pages/man5/utmp.5.html">utmp(5)</a> to include the controlling TTY and session ID,
to track the current active sessions.</p>
<p>There are a number of issues with using UNIX sessions for tracking processes.</p>
<ol>
<li><p><a href="http://man7.org/linux/man-pages/man5/utmp.5.html">utmp(5)</a> is an awkward interface,
requiring multiple processes to access a single file
without trampling over each other,
requiring file range locking,
which can't be done portably and in a thread-safe manner.</p>
<p>I consider this to be analogous to <a href="https://en.wikipedia.org/wiki/Mtab">/etc/mtab</a>,
which was an old, manually maintained file,
which had to be replaced with a more reliable, kernel-provided interface.</p></li>
<li><p><a href="http://man7.org/linux/man-pages/man2/setsid.2.html">setsid(2)</a> describes sessions and process groups
as a strict two-level hierarchy.</p>
<p>The implication of this is that any process can escape with <a href="http://man7.org/linux/man-pages/man2/setsid.2.html">setsid(2)</a>,
so bypassing <a href="https://en.wikipedia.org/wiki/Mtab">mtab</a>
and inspecting the contents of the <code>sessionid</code> flie in <code>/proc</code> won't work.</p></li>
<li><p>Escaping session cleanup is by necessity a well-documented procedure,
since traditional daemons are started by detaching from the current session
rather than asking the <a href="https://en.wikipedia.org/wiki/Init">init</a> process to start the daemon.</p>
<p>See <a href="http://man7.org/linux/man-pages/man1/nohup.1.html">nohup(1)</a> for details about how to escape session cleanup.</p></li>
</ol>
<h1>Conclusion</h1>
<p>The traditional UNIX system calls came from a time
when it was believed you could trust programs to be well written and benign.</p>
<p>We do not live in this world,
so we need a better approach to track which processes we run on our computers,
which we will discuss in a future article.</p>