tty: fix ClearONLCR race

The TestExecInTTY test case is sometimes failing like this:

> execin_test.go:332: unexpected carriage-return in output "PID USER TIME COMMAND\r\n 1 root 0:00 cat\r\n 7 root 0:00 ps\r\n"

or this:

> execin_test.go:332: unexpected carriage-return in output "PID USER TIME COMMAND\r\n 1 root 0:00 cat\n 7 root 0:00 ps\n"

(this is easy to repro with `go test -run TestExecInTTY -count 1000`).

This is caused by a race between

 - an Init() (in this case it is is (*linuxSetnsInit.Init(), but
   (*linuxStandardInit).Init() is no different in this regard),
   which creates a pty pair, sends pty master to runc, and execs
   the container process,

and

 - a parent runc process, which receives the pty master fd and calls
   ClearONLCR() on it.

One way of fixing it would be to add a synchronization mechanism
between these two, so Init() won't exec the process until the parent
sets the flag. This seems excessive, though, as we can just move
the ClearONLCR() call to Init(), putting it right after console.NewPty().

Note that bug only happens in the TestExecInTTY test case, but
from looking at the code it seems like it can happen in runc run
or runc exec, too.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin
2021-01-07 09:11:59 -08:00
parent 04b7b7d3c3
commit 24c05b71fa
4 changed files with 4 additions and 8 deletions

View File

@@ -106,9 +106,6 @@ func handleSingle(path string, noStdin bool) error {
if err != nil {
return err
}
if err := console.ClearONLCR(c.Fd()); err != nil {
return err
}
// Copy from our stdio to the master fd.
var (

View File

@@ -186,6 +186,10 @@ func setupConsole(socket *os.File, config *initConfig, mount bool) error {
if err != nil {
return err
}
err = console.ClearONLCR(pty.Fd())
if err != nil {
return err
}
// After we return from here, we don't need the console anymore.
defer pty.Close()

View File

@@ -313,7 +313,6 @@ func TestExecInTTY(t *testing.T) {
}
return
}
console.ClearONLCR(c.Fd())
dc <- &cdata{
c: c,
}

4
tty.go
View File

@@ -112,10 +112,6 @@ func (t *tty) recvtty(process *libcontainer.Process, socket *os.File) (Err error
if err != nil {
return err
}
err = console.ClearONLCR(cons.Fd())
if err != nil {
return err
}
epoller, err := console.NewEpoller()
if err != nil {
return err