]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
script: improve I/O return code checks
authorSoumendra Ganguly <soumendraganguly@gmail.com>
Tue, 15 Sep 2020 14:14:59 +0000 (09:14 -0500)
committerKarel Zak <kzak@redhat.com>
Mon, 21 Sep 2020 10:58:15 +0000 (12:58 +0200)
Handle error based on return code of handle_io() and handle_signal().
Keep SIGTTIN unblocked during read() in handle_io().

Signed-off-by: Soumendra Ganguly <soumendraganguly@gmail.com>
lib/pty-session.c

index 06b2a49d66f4397d0002a8285b0b94551d995f5f..4cf29d6ddd2c8f37c72a5ff0057f1ffdcf58821e 100644 (file)
@@ -340,12 +340,17 @@ static int handle_io(struct ul_pty *pty, int fd, int *eof)
        char buf[BUFSIZ];
        ssize_t bytes;
        int rc = 0;
+       sigset_t set;
 
        DBG(IO, ul_debugobj(pty, " handle I/O on fd=%d", fd));
        *eof = 0;
 
+       sigemptyset(&set);
+       sigaddset(&set, SIGTTIN);
+       sigprocmask(SIG_UNBLOCK, &set, NULL);
        /* read from active FD */
        bytes = read(fd, buf, sizeof(buf));
+       sigprocmask(SIG_BLOCK, &set, NULL);
        if (bytes < 0) {
                if (errno == EAGAIN || errno == EINTR)
                        return 0;
@@ -409,8 +414,8 @@ void ul_pty_wait_for_child(struct ul_pty *pty)
                }
        } else {
                /* final wait */
-               while ((pid = wait3(&status, options, NULL)) > 0) {
-                       DBG(SIG, ul_debug(" wait3 done [rc=%d]", (int) pid));
+               while ((pid = waitpid(-1, &status, options)) > 0) {
+                       DBG(SIG, ul_debug(" waitpid done [rc=%d]", (int) pid));
                        if (pid == pty->child) {
                                if (pty->callbacks.child_die)
                                        pty->callbacks.child_die(
@@ -451,9 +456,10 @@ static int handle_signal(struct ul_pty *pty, int fd)
                        else
                                ul_pty_wait_for_child(pty);
 
-               } else if (info.ssi_status == SIGSTOP && pty->child > 0)
+               } else if (info.ssi_status == SIGSTOP && pty->child > 0) {
                        pty->callbacks.child_sigstop(pty->callback_data,
                                                     pty->child);
+               }
 
                if (pty->child <= 0) {
                        DBG(SIG, ul_debugobj(pty, " no child, setting leaving timeout"));
@@ -571,16 +577,15 @@ int ul_pty_proxy_master(struct ul_pty *pty)
                                rc = mainloop_callback(pty);
                                if (rc == 0)
                                        continue;
-                       } else
+                       } else {
                                rc = 0;
+                       }
 
                        DBG(IO, ul_debugobj(pty, "leaving poll() loop [timeout=%d, rc=%d]", timeout, rc));
                        break;
                }
                /* event */
                for (i = 0; i < ARRAY_SIZE(pfd); i++) {
-                       rc = 0;
-
                        if (pfd[i].revents == 0)
                                continue;
 
@@ -594,34 +599,36 @@ int ul_pty_proxy_master(struct ul_pty *pty)
                                                pfd[i].revents & POLLERR ? "POLLERR" : "",
                                                pfd[i].revents & POLLNVAL ? "POLLNVAL" : ""));
 
-                       switch (i) {
-                       case POLLFD_STDIN:
-                       case POLLFD_MASTER:
-                               /* data */
-                               if (pfd[i].revents & POLLIN)
-                                       rc = handle_io(pty, pfd[i].fd, &eof);
-                               /* EOF maybe detected in two ways; they are as follows:
-                                *      A) poll() return POLLHUP event after close()
-                                *      B) read() returns 0 (no data)
-                                *
-                                * POLLNVAL means that fd is closed.
-                                */
-                               if ((pfd[i].revents & POLLHUP) || (pfd[i].revents & POLLNVAL) || eof) {
-                                       DBG(IO, ul_debugobj(pty, " ignore FD"));
-                                       pfd[i].fd = -1;
-                                       if (i == POLLFD_STDIN) {
-                                               ul_pty_write_eof_to_child(pty);
-                                               DBG(IO, ul_debugobj(pty, "  ignore STDIN"));
-                                       }
-                               }
-                               continue;
-                       case POLLFD_SIGNAL:
+                       if (i == POLLFD_SIGNAL)
                                rc = handle_signal(pty, pfd[i].fd);
+                       else if (pfd[i].revents & POLLIN)
+                               rc = handle_io(pty, pfd[i].fd, &eof); /* data */
+
+                       if (rc) {
+                               ul_pty_write_eof_to_child(pty);
                                break;
                        }
-                       if (rc)
-                               break;
+
+                       if (i == POLLFD_SIGNAL)
+                               continue;
+
+                       /* EOF maybe detected in two ways; they are as follows:
+                        *      A) poll() return POLLHUP event after close()
+                        *      B) read() returns 0 (no data)
+                        *
+                        * POLLNVAL means that fd is closed.
+                        */
+                       if ((pfd[i].revents & POLLHUP) || (pfd[i].revents & POLLNVAL) || eof) {
+                               DBG(IO, ul_debugobj(pty, " ignore FD"));
+                               pfd[i].fd = -1;
+                               if (i == POLLFD_STDIN) {
+                                       ul_pty_write_eof_to_child(pty);
+                                       DBG(IO, ul_debugobj(pty, "  ignore STDIN"));
+                               }
+                       }
                }
+               if (rc)
+                       break;
        }
 
        pty_signals_cleanup(pty);