summaryrefslogtreecommitdiff
path: root/Src/Zle/zle_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle/zle_main.c')
-rw-r--r--Src/Zle/zle_main.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index b0010fc33..442c31995 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -525,7 +525,8 @@ raw_getbyte(long do_keytmout, char *cptr)
#endif
#ifndef HAVE_POLL
# ifdef HAVE_SELECT
- fd_set foofd;
+ fd_set foofd, errfd;
+ FD_ZERO(&errfd);
# endif
#endif
@@ -613,11 +614,14 @@ raw_getbyte(long do_keytmout, char *cptr)
if (!errtry) {
for (i = 0; i < nwatch; i++) {
int fd = watch_fds[i].fd;
+ if (FD_ISSET(fd, &errfd))
+ continue;
FD_SET(fd, &foofd);
if (fd > fdmax)
fdmax = fd;
}
}
+ FD_ZERO(&errfd);
if (tmout.tp != ZTM_NONE) {
expire_tv.tv_sec = tmout.exp100ths / 100;
@@ -732,9 +736,10 @@ raw_getbyte(long do_keytmout, char *cptr)
Watch_fd lwatch_fd = lwatch_fds + i;
if (
# ifdef HAVE_POLL
- (fds[i+1].revents & POLLIN)
+ (fds[i+1].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL))
# else
- FD_ISSET(lwatch_fd->fd, &foofd)
+ FD_ISSET(lwatch_fd->fd, &foofd) ||
+ FD_ISSET(lwatch_fd->fd, &errfd)
# endif
) {
/* Handle the fd. */
@@ -765,6 +770,9 @@ raw_getbyte(long do_keytmout, char *cptr)
if (fds[i+1].revents & POLLNVAL)
zaddlinknode(funcargs, ztrdup("nval"));
# endif
+# else
+ if (FD_ISSET(lwatch_fd->fd, &errfd))
+ zaddlinknode(funcargs, ztrdup("err"));
# endif
callhookfunc(lwatch_fd->func, funcargs, 0, NULL);
freelinklist(funcargs, freestr);
@@ -786,6 +794,31 @@ raw_getbyte(long do_keytmout, char *cptr)
for (i = 0; i < lnwatch; i++)
zsfree(lwatch_fds[i].func);
zfree(lwatch_fds, lnwatch*sizeof(struct watch_fd));
+
+# ifdef HAVE_POLL
+ /* Function may have added or removed handlers */
+ nfds = 1 + nwatch;
+ if (nfds > 1) {
+ fds = zrealloc(fds, sizeof(struct pollfd) * nfds);
+ for (i = 0; i < nwatch; i++) {
+ /*
+ * This is imperfect because it assumes fds[] and
+ * watch_fds[] remain in sync, which may be false
+ * if handlers are shuffled. However, it should
+ * be harmless (e.g., produce one extra pass of
+ * the loop) in the event they fall out of sync.
+ */
+ if (fds[i+1].fd == watch_fds[i].fd &&
+ (fds[i+1].revents & (POLLERR|POLLHUP|POLLNVAL))) {
+ fds[i+1].events = 0; /* Don't poll this */
+ } else {
+ fds[i+1].fd = watch_fds[i].fd;
+ fds[i+1].events = POLLIN;
+ }
+ fds[i+1].revents = 0;
+ }
+ }
+# endif
}
}
# ifdef HAVE_POLL