X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/24c7dc5c3c73e44a00357631a21e3b6d6c75a5df..4643740aa6f3eac7d3dfab05967ec55b5d8ba984:/sys/kern/sys_generic.c diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 45576e7016..9e46223c6c 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -891,7 +891,7 @@ sys_pselect(struct pselect_args *uap) * us. So make a note to restore it after executing * the handler. */ - lp->lwp_flag |= LWP_OLDMASK; + lp->lwp_flags |= LWP_OLDMASK; } else { /* * No handler to run. Restore previous mask immediately. @@ -1021,16 +1021,18 @@ select_copyout(void *arg, struct kevent *kevp, int count, int *res) * Handle errors */ if (kevp[i].flags & EV_ERROR) { - switch(kevp[i].data) { + int error = kevp[i].data; + + switch (error) { case EBADF: /* * A bad file descriptor is considered a * fatal error for select, bail out. */ - skap->error = EBADF; - *res = 0; - return (1); - break; + skap->error = error; + *res = -1; + return error; + default: /* * Select silently swallows any unknown errors @@ -1042,18 +1044,17 @@ select_copyout(void *arg, struct kevent *kevp, int count, int *res) */ if (kevp[i].filter != EVFILT_READ && kevp[i].filter != EVFILT_WRITE && - kevp[i].data != EOPNOTSUPP) { - skap->error = kevp[i].data; - *res = 0; - return (1); + error != EOPNOTSUPP) { + skap->error = error; + *res = -1; + return error; } break; } if (nseldebug) - kprintf("select fd %ju filter %d error %jd\n", + kprintf("select fd %ju filter %d error %d\n", (uintmax_t)kevp[i].ident, - kevp[i].filter, - (intmax_t)kevp[i].data); + kevp[i].filter, error); continue; } @@ -1113,6 +1114,12 @@ putbits(int bytes, kfd_set *in_set, fd_set *out_set) return (error); } +static int +dotimeout_only(struct timespec *ts) +{ + return(nanosleep1(ts, NULL)); +} + /* * Common code for sys_select() and sys_pselect(). * @@ -1134,6 +1141,9 @@ doselect(int nd, fd_set *read, fd_set *write, fd_set *except, *res = 0; if (nd < 0) return (EINVAL); + if (nd == 0) + return (dotimeout_only(ts)); + if (nd > p->p_fd->fd_nfiles) /* limit kmalloc */ nd = p->p_fd->fd_nfiles; @@ -1374,14 +1384,17 @@ poll_copyout(void *arg, struct kevent *kevp, int count, int *res) case EVFILT_READ: #if 0 /* - * EOF on the read side can indicate a + * NODATA on the read side can indicate a * half-closed situation and not necessarily * a disconnect, so depend on the user * issuing a read() and getting 0 bytes back. */ - if (kevp[i].flags & EV_EOF) + if (kevp[i].flags & EV_NODATA) pfd->revents |= POLLHUP; #endif + if ((kevp[i].flags & EV_EOF) && + kevp[i].fflags != 0) + pfd->revents |= POLLERR; if (pfd->events & POLLIN) pfd->revents |= POLLIN; if (pfd->events & POLLRDNORM) @@ -1398,6 +1411,8 @@ poll_copyout(void *arg, struct kevent *kevp, int count, int *res) */ if (kevp[i].flags & EV_EOF) { pfd->revents |= POLLHUP; + if (kevp[i].fflags != 0) + pfd->revents |= POLLERR; } else { if (pfd->events & POLLOUT) pfd->revents |= POLLOUT; @@ -1407,7 +1422,7 @@ poll_copyout(void *arg, struct kevent *kevp, int count, int *res) break; case EVFILT_EXCEPT: /* - * EV_EOF should never be tagged for this + * EV_NODATA should never be tagged for this * filter. */ if (pfd->events & POLLPRI) @@ -1447,6 +1462,9 @@ dopoll(int nfds, struct pollfd *fds, struct timespec *ts, int *res) if (nfds < 0) return (EINVAL); + if (nfds == 0) + return (dotimeout_only(ts)); + /* * This is a bit arbitrary but we need to limit internal kmallocs. */