<html>
<head>
<base href="https://bugs.freedesktop.org/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Priority</th>
<td>medium
</td>
</tr>
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - [systemd-nspawn] Doesn't correctly handle std{in,out} not being the same file, and not being a TTY"
href="https://bugs.freedesktop.org/show_bug.cgi?id=70290">70290</a>
</td>
</tr>
<tr>
<th>Assignee</th>
<td>systemd-bugs@lists.freedesktop.org
</td>
</tr>
<tr>
<th>Summary</th>
<td>[systemd-nspawn] Doesn't correctly handle std{in,out} not being the same file, and not being a TTY
</td>
</tr>
<tr>
<th>QA Contact</th>
<td>systemd-bugs@lists.freedesktop.org
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Reporter</th>
<td>lukeshu@sbcglobal.net
</td>
</tr>
<tr>
<th>Hardware</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Component</th>
<td>general
</td>
</tr>
<tr>
<th>Product</th>
<td>systemd
</td>
</tr></table>
<p>
<div>
<pre>This is actually a large, compound bug that results in "it doesn't do the right
thing if you redirect stdio".
Bugs 1-2 mean redirecting stdout doesn't work correctly.
<a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED FIXED - Should provide empty local.conf file"
href="show_bug.cgi?id=3">Bug 3</a> means that redirecting/closing stdin doesn't work correctly.
(possible) <a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED FIXED - Typo in fonts.conf.in"
href="show_bug.cgi?id=4">Bug 4</a> means that even if <a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED FIXED - Should provide empty local.conf file"
href="show_bug.cgi?id=3">bug 3</a> is fixed, redirecting stdin doesn't
work as expected.
(possible) <a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED INVALID - unending memory allocation?"
href="show_bug.cgi?id=5">Bug 5</a> means that even if bugs 1-2 are fixed, redirecting stdout
doesn't work as expected.
A quick note on nomenclature: systemd-nspawn creates/acquires a PTY that is
used for /dev/console in the chroot. I will refer to this as the "proxy PTY".
<a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED FIXED - Optimizations"
href="show_bug.cgi?id=1">Bug 1</a>: It bases the dimensions of the proxy PTY off of the dimensions of stdin,
not stdout.
This is a 1-line change, to change `ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)` to
use `STDOUT_FILENO`.
<a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED FIXED - submake invocation failure does not cause build failure"
href="show_bug.cgi?id=2">Bug 2</a>: It sets the output properties of stdin (if it is a TTY).
This is wrong if stdin and stdout are not the same file. It gets stdin's
terminal attributes (tcgetattr), runs the through cfmakeraw, and saves them
back (tcsetattr). The problem is that cfmakeraw sets both input and output
attributes. The simplest work-around is to set `raw_attr.c_oflag =
saved_attr.c_oflag` after running `cfmakeraw(&raw_attr)`.
(PS: it also unset the ECHO local flag on raw_attr after running it through
cfmakeraw, which already did that. That line was superfluous.)
But then, the output properties of stdout are not set--we must then do a
similar process for it, but resetting attr.c_iflag, attr.c_lflag, and
attr.c_cc.
We must also, set one before starting to set the other (set stdin before
reading the current values for stdout), or the second write will reset the
first one.
<a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED FIXED - Should provide empty local.conf file"
href="show_bug.cgi?id=3">Bug 3</a>: If stdin is not a TTY, it has no form of signal handling.
(the following applies to all signals that a TTY may generate, but I will only
speak of SIGINT)
The "signal handling" currently employed is "hey, stdin, if you see C-c, don't
send me SIGINT, just let me read C-c as input" (through the call to cfmakeraw
mentioned above). It then passes C-c to the proxy PTY, which translates it
into a SIGINT to be sent to the child process.
This means two things: 1) If stdin isn't a TTY, it's "signal handling" won't
work. 2) If it receives a "signal" from anything other than a terminal, it
won't respond correctly.
So, what happens if the signal handling isn't working. When it receives
SIGINT, it dies, it stops proxying data between the proxy PTY and stdin/stdout.
This causes either the child process to starve on stdin, or fill the proxy
PTY's buffer and block. Either way, it causes an I/O block, and the child
process(es) will need to be kill(1)ed.
The simplest work-around would be to open /dev/tty, and set *that* to not
interpret C-c as SIGINT; that way the TTY is set even if it isn't stdin.
However, that only fixes consequence 1 above, not consequence 2.
(possible) <a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED FIXED - Typo in fonts.conf.in"
href="show_bug.cgi?id=4">Bug 4</a>: If stdin is not a TTY, it does not read stdin.
(possible) <a class="bz_bug_link
bz_status_RESOLVED bz_closed"
title="RESOLVED INVALID - unending memory allocation?"
href="show_bug.cgi?id=5">Bug 5</a>: If stdout is not a TTY, it represents stdout as a TTY to the
child process.
In my opinion, the correct behaviour here would be to set up the proxy PTY as
/dev/console in the chroot, but not set it to stdin/out/err. Instead, open a
pipe that is used to proxy between the child process' I/O, and systemd-nspawn's
I/O.
Whether or not you agree with that, if stdin is open, I don't think it's
reasonable to ignore it.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are the QA Contact for the bug.</li>
<li>You are the assignee for the bug.</li>
</ul>
</body>
</html>