From 9e97cfa052cba672d68dd6e7dfd7628719eda5aa Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 6 Jun 2002 09:04:46 +0000 Subject: 17293: support poll() as preferred alternative to select() in zle --- ChangeLog | 5 +++ Doc/Zsh/zle.yo | 4 +- Src/Zle/zle_main.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 111 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 992c53b4f..618d31c41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2002-06-06 Peter Stephenson + + * 17293: Src/Zle/zle_main.c, Doc/Zsh/zle.yo: support poll() + as a (preferred) alternative to select() in zle. + 2002-06-06 Clint Adams * 17297: Src/Modules/zpty.c: 17265 continued. diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 67e66830d..bfdbbd736 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -413,8 +413,8 @@ within this invocation of ZLE. Any following invocation (e.g., the next command line) will start as usual with the `tt(main)' keymap selected. ) item(tt(-F) [ tt(-L) ] [ var(fd) [ var(handler) ] ])( -Only available if your system support the `select' system call; most -modern systems do. +Only available if your system supports one of the `poll' or `select' system +calls; most modern systems do. Installs var(handler) (the name of a shell function) to handle input from file descriptor var(fd). When zle is attempting to read data, it will diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 56797a9a9..782bd472c 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -30,6 +30,13 @@ #include "zle.mdh" #include "zle_main.pro" +#ifdef HAVE_POLL_H +# include +#endif +#if defined(HAVE_POLL) && !defined(POLLIN) && !defined(POLLNORM) +# undef HAVE_POLL +#endif + /* != 0 if in a shell function called from completion, such that read -[cl] * * will work (i.e., the line is metafied, and the above word arrays are OK). */ @@ -340,11 +347,13 @@ raw_getkey(int keytmout, char *cptr) { long exp100ths; int ret; -#ifdef HAVE_SELECT +#ifndef HAVE_POLL +# ifdef HAVE_SELECT fd_set foofd; -#else -# ifdef HAS_TIO +# else +# ifdef HAS_TIO struct ttyinfo ti; +# endif # endif #endif @@ -364,18 +373,45 @@ raw_getkey(int keytmout, char *cptr) exp100ths = 500; else exp100ths = keytimeout; -#ifdef HAVE_SELECT +#if defined(HAVE_SELECT) || defined(HAVE_POLL) if (!keytmout || exp100ths) { + int i, errtry = 0, selret; +# ifdef HAVE_POLL + int poll_timeout; + int nfds = keytmout ? 1 : 1 + nwatch; + /* First pollfd is SHTTY, following are the nwatch fds */ + struct pollfd *fds = zalloc(sizeof(struct pollfd) * nfds); + if (exp100ths) + poll_timeout = exp100ths * 10; + else + poll_timeout = -1; + + fds[0].fd = SHTTY; + /* + * POLLIN, POLLIN, POLLIN, + * Keep those fd's POLLIN... + */ + fds[0].events = POLLIN; + if (!keytmout) { + for (i = 0; i < nwatch; i++) { + fds[i+1].fd = watch_fds[i]; + fds[i+1].events = POLLIN; + } + } +# else + int fdmax = SHTTY; struct timeval *tvptr = NULL; struct timeval expire_tv; - int i, fdmax = SHTTY, errtry = 0; if (exp100ths) { expire_tv.tv_sec = exp100ths / 100; expire_tv.tv_usec = (exp100ths % 100) * 10000L; tvptr = &expire_tv; } +# endif do { - int selret; +# ifdef HAVE_POLL + selret = poll(fds, errtry ? 1 : nfds, poll_timeout); +# else FD_ZERO(&foofd); FD_SET(SHTTY, &foofd); if (!keytmout && !errtry) { @@ -388,11 +424,12 @@ raw_getkey(int keytmout, char *cptr) } selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, tvptr); +# endif /* * Make sure a user interrupt gets passed on straight away. */ if (selret < 0 && errflag) - return selret; + break; /* * Try to avoid errors on our special fd's from * messing up reads from the terminal. Try first @@ -404,9 +441,10 @@ raw_getkey(int keytmout, char *cptr) } if (selret == 0) { /* Special value -2 signals nothing ready */ - return -2; - } else if (selret < 0) - return selret; + selret = -2; + } + if (selret < 0) + break; if (!keytmout && nwatch) { /* * Copy the details of the watch fds in case the @@ -418,7 +456,13 @@ raw_getkey(int keytmout, char *cptr) char **lwatch_funcs = zarrdup(watch_funcs); memcpy(lwatch_fds, watch_fds, lnwatch*sizeof(int)); for (i = 0; i < lnwatch; i++) { - if (FD_ISSET(lwatch_fds[i], &foofd)) { + if ( +# ifdef HAVE_POLL + (fds[i+1].revents & POLLIN) +# else + FD_ISSET(lwatch_fds[i], &foofd) +# endif + ) { /* Handle the fd. */ LinkList funcargs = znewlinklist(); zaddlinknode(funcargs, ztrdup(lwatch_funcs[i])); @@ -427,6 +471,21 @@ raw_getkey(int keytmout, char *cptr) convbase(buf, lwatch_fds[i], 10); zaddlinknode(funcargs, ztrdup(buf)); } +# ifdef HAVE_POLL +# ifdef POLLERR + if (fds[i+1].revents & POLLERR) + zaddlinknode(funcargs, ztrdup("err")); +# endif +# ifdef POLLHUP + if (fds[i+1].revents & POLLHUP) + zaddlinknode(funcargs, ztrdup("hup")); +# endif +# ifdef POLLNVAL + if (fds[i+1].revents & POLLNVAL) + zaddlinknode(funcargs, ztrdup("nval")); +# endif +# endif + callhookfunc(lwatch_funcs[i], funcargs); if (errflag) { @@ -447,7 +506,18 @@ raw_getkey(int keytmout, char *cptr) zfree(lwatch_fds, lnwatch*sizeof(int)); freearray(lwatch_funcs); } - } while (!FD_ISSET(SHTTY, &foofd)); + } while (! +# ifdef HAVE_POLL + (fds[0].revents & POLLIN) +# else + FD_ISSET(SHTTY, &foofd) +# endif + ); +# ifdef HAVE_POLL + zfree(fds, sizeof(struct pollfd) * nfds); +# endif + if (selret < 0) + return selret; } #else # ifdef HAS_TIO @@ -571,10 +641,13 @@ zleread(char *lp, char *rp, int flags) int old_errno = errno; int tmout = getiparam("TMOUT"); -#ifdef HAVE_SELECT +#if defined(HAVE_SELECT) || defined(HAVE_POLL) long costmult; +# ifdef HAVE_POLL +# else struct timeval tv; fd_set foofd; +# endif baud = getiparam("BAUD"); costmult = (baud) ? 3840000L / baud : 0; @@ -620,8 +693,10 @@ zleread(char *lp, char *rp, int flags) zlereadflags = flags; histline = curhist; -#ifdef HAVE_SELECT +#ifndef HAVE_POLL +# ifdef HAVE_SELECT FD_ZERO(&foofd); +# endif #endif undoing = 1; line = (unsigned char *)zalloc((linesz = 256) + 2); @@ -683,7 +758,20 @@ zleread(char *lp, char *rp, int flags) errflag = 1; break; } -#ifdef HAVE_SELECT +#ifdef HAVE_POLL + if (baud && !(lastcmd & ZLE_MENUCMP)) { + struct pollfd pfd; + int to = cost * costmult / 1000; /* milliseconds */ + + if (to > 500) + to = 500; + pfd.fd = SHTTY; + pfd.events = POLLIN; + if (!kungetct && poll(&pfd, 1, to) <= 0) + zrefresh(); + } else +#else +# ifdef HAVE_SELECT if (baud && !(lastcmd & ZLE_MENUCMP)) { FD_SET(SHTTY, &foofd); tv.tv_sec = 0; @@ -693,6 +781,7 @@ zleread(char *lp, char *rp, int flags) NULL, NULL, &tv) <= 0) zrefresh(); } else +# endif #endif if (!kungetct) zrefresh(); -- cgit 1.4.1