terminal: make a terminal FDs non-blocking

Let's prevent freezes on read(2) by making a terminal FDs non-blocking.

It was discovered that there is an issue with io_uring mainloop when
multishot poll (IORING_POLL_ADD_MULTI) mode is enabled. Sometimes
false-positive poll events are put into a CQ. It makes further read(2)
stuck forever and blocks all mainloop processing for an infinite time.

Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
This commit is contained in:
Alexander Mikhalitsyn 2023-04-21 18:38:53 +02:00
parent 7eff16cc4c
commit 715fb4effa
No known key found for this signature in database
GPG Key ID: B1F47F5CB05B4FA3

View File

@ -334,9 +334,12 @@ static int lxc_terminal_ptx_io(struct lxc_terminal *terminal)
int r, w, w_log, w_rbuf;
w = r = lxc_read_nointr(terminal->ptx, buf, sizeof(buf));
if (r <= 0)
return -1;
if (r <= 0) {
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
w_rbuf = w_log = 0;
/* write to peer first */
if (terminal->peer >= 0)
@ -370,8 +373,12 @@ static int lxc_terminal_peer_io(struct lxc_terminal *terminal)
int r, w;
w = r = lxc_read_nointr(terminal->peer, buf, sizeof(buf));
if (r <= 0)
if (r <= 0) {
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
w = lxc_write_nointr(terminal->ptx, buf, r);
if (w != r)
@ -415,6 +422,9 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal)
int ret;
if (terminal->peer >= 0) {
if (fd_make_nonblocking(terminal->peer))
return log_error_errno(-1, errno, "Failed to make terminal peer fd non-blocking");
ret = lxc_mainloop_add_handler(terminal->descr, terminal->peer,
lxc_terminal_peer_io_handler,
default_cleanup_handler,
@ -452,6 +462,9 @@ int lxc_terminal_mainloop_add(struct lxc_async_descr *descr,
return 0;
}
if (fd_make_nonblocking(terminal->ptx))
return log_error_errno(-1, errno, "Failed to make terminal ptx fd non-blocking");
ret = lxc_mainloop_add_handler(descr, terminal->ptx,
lxc_terminal_ptx_io_handler,
default_cleanup_handler,