diff options
author | Todd C. Miller <Todd.Miller@sudo.ws> | 2022-06-07 12:40:00 -0600 |
---|---|---|
committer | Todd C. Miller <Todd.Miller@sudo.ws> | 2022-06-07 12:40:00 -0600 |
commit | b13c8d47935e5fd5548fefbd25acad17f98cf00e (patch) | |
tree | 766d43860c66720525d84686ed30f399d6d35db3 | |
parent | 1e31f3a22a9535ba61dfd5f0aa33789b2f09aed9 (diff) | |
download | sudo-b13c8d47935e5fd5548fefbd25acad17f98cf00e.tar.gz |
Make read and write events persistent and disable as needed.
For the read callback, disable reader when the buffer is full.
For the write callback, disable writer when the buffer is consumed.
-rw-r--r-- | src/exec_pty.c | 34 |
1 files changed, 13 insertions, 21 deletions
diff --git a/src/exec_pty.c b/src/exec_pty.c index d2fc1ce5c..e2fd9c60e 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -677,12 +677,10 @@ read_callback(int fd, int what, void *v) schedule_signal(iob->ec, SIGTTIN); } if (errno == EAGAIN || errno == EINTR) { - /* Re-enable reader. */ - if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1) - sudo_fatal("%s", U_("unable to add event to queue")); + /* Not an error, retry later. */ break; } - /* treat read error as fatal and close the fd */ + /* Treat read error as fatal and close the fd. */ sudo_debug_printf(SUDO_DEBUG_ERROR, "error reading fd %d: %s", fd, strerror(errno)); FALLTHROUGH; @@ -709,16 +707,14 @@ read_callback(int fd, int what, void *v) iob->ec->cmnd_pid = -1; } iob->len += n; - /* Enable writer now that there is data in the buffer. */ + /* Disable reader if buffer is full. */ + if (iob->len == sizeof(iob->buf)) + sudo_ev_del(evbase, iob->revent); + /* Enable writer now that there is new data in the buffer. */ if (iob->wevent != NULL) { if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1) sudo_fatal("%s", U_("unable to add event to queue")); } - /* Re-enable reader if buffer is not full. */ - if (iob->len != sizeof(iob->buf)) { - if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1) - sudo_fatal("%s", U_("unable to add event to queue")); - } break; } @@ -789,9 +785,7 @@ write_callback(int fd, int what, void *v) } FALLTHROUGH; case EAGAIN: - /* Not an error, re-enable writer. */ - if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1) - sudo_fatal("%s", U_("unable to add event to queue")); + /* Not an error, retry later. */ break; default: /* XXX - need a way to distinguish non-exec error. */ @@ -806,20 +800,16 @@ write_callback(int fd, int what, void *v) sudo_debug_printf(SUDO_DEBUG_INFO, "wrote %zd bytes to fd %d", n, fd); iob->off += n; - /* Reset buffer if fully consumed. */ + /* Disable writer and reset the buffer if fully consumed. */ if (iob->off == iob->len) { iob->off = iob->len = 0; + sudo_ev_del(evbase, iob->wevent); /* Forward the EOF from reader to writer. */ if (iob->revent == NULL) { safe_close(fd); ev_free_by_fd(evbase, fd); } } - /* Re-enable writer if buffer is not empty. */ - if (iob->len > iob->off) { - if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1) - sudo_fatal("%s", U_("unable to add event to queue")); - } /* Enable reader if buffer is not full. */ if (iob->revent != NULL && (ttymode == TERM_RAW || !USERTTY_EVENT(iob->revent))) { @@ -854,8 +844,10 @@ io_buf_new(int rfd, int wfd, if ((iob = malloc(sizeof(*iob))) == NULL) sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); iob->ec = ec; - iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ, read_callback, iob); - iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE, write_callback, iob); + iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ|SUDO_EV_PERSIST, + read_callback, iob); + iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE|SUDO_EV_PERSIST, + write_callback, iob); iob->len = 0; iob->off = 0; iob->action = action; |