]> git.proxmox.com Git - mirror_lxc.git/commitdiff
terminal: make a terminal FDs non-blocking
authorAlexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Fri, 21 Apr 2023 16:38:53 +0000 (18:38 +0200)
committerAlexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Fri, 21 Apr 2023 16:53:49 +0000 (18:53 +0200)
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>
src/lxc/terminal.c

index a1dcc2dc7750fcb9a1b62e0451d8a1b8b3586e78..de4328fb799a08e582d3c6efe867f8945197d4f5 100644 (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,