$NetBSD: patch-ac,v 1.7 2010/08/06 19:21:27 drochner Exp $ --- pth_high.c.orig 2006-06-08 17:54:03.000000000 +0000 +++ pth_high.c @@ -184,6 +184,35 @@ int pth_sigwait_ev(const sigset_t *set, return 0; } +#ifdef HAVE_SYS_RESOURCE_H +/* Pth variant of wait4(2) */ +pid_t pth_wait4(pid_t wpid, int *status, int options, struct rusage *rusage) +{ + pth_event_t ev; + static pth_key_t ev_key = PTH_KEY_INIT; + pid_t pid; + + pth_debug2("pth_wait4: called from thread \"%s\"", pth_current->name); + + for (;;) { + /* do a non-blocking poll for the pid */ + while ( (pid = pth_sc(wait4)(wpid, status, options|WNOHANG, rusage)) < 0 + && errno == EINTR) ; + + /* if pid was found or caller requested a polling return immediately */ + if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG))) + break; + + /* else wait a little bit */ + ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, pth_timeout(0,250000)); + pth_wait(ev); + } + + pth_debug2("pth_wait4: leave to thread \"%s\"", pth_current->name); + return pid; +} +#endif + /* Pth variant of waitpid(2) */ pid_t pth_waitpid(pid_t wpid, int *status, int options) { @@ -334,9 +363,9 @@ int pth_select_ev(int nfd, fd_set *rfds, } } /* POSIX.1-2001/SUSv3 compliance */ - if (rfds != NULL) FD_ZERO(rfds); - if (wfds != NULL) FD_ZERO(wfds); - if (efds != NULL) FD_ZERO(efds); + if (rfds != NULL) pth_util_fd_zero(nfd, rfds); + if (wfds != NULL) pth_util_fd_zero(nfd, wfds); + if (efds != NULL) pth_util_fd_zero(nfd, efds); return 0; } @@ -349,17 +378,17 @@ int pth_select_ev(int nfd, fd_set *rfds, delay.tv_usec = 0; rtmp = NULL; if (rfds != NULL) { - memcpy(&rspare, rfds, sizeof(fd_set)); + pth_util_fd_copy(nfd, &rspare, rfds); rtmp = &rspare; } wtmp = NULL; if (wfds != NULL) { - memcpy(&wspare, wfds, sizeof(fd_set)); + pth_util_fd_copy(nfd, &wspare, wfds); wtmp = &wspare; } etmp = NULL; if (efds != NULL) { - memcpy(&espare, efds, sizeof(fd_set)); + pth_util_fd_copy(nfd, &espare, efds); etmp = &espare; } while ((rc = pth_sc(select)(nfd, rtmp, wtmp, etmp, &delay)) < 0 @@ -374,11 +403,11 @@ int pth_select_ev(int nfd, fd_set *rfds, && pth_time_cmp(timeout, PTH_TIME_ZERO) == 0)) { /* pass-through immediate success */ if (rfds != NULL) - memcpy(rfds, &rspare, sizeof(fd_set)); + pth_util_fd_copy(nfd, rfds, &rspare); if (wfds != NULL) - memcpy(wfds, &wspare, sizeof(fd_set)); + pth_util_fd_copy(nfd, wfds, &wspare); if (efds != NULL) - memcpy(efds, &espare, sizeof(fd_set)); + pth_util_fd_copy(nfd, efds, &espare); return rc; } @@ -411,9 +440,9 @@ int pth_select_ev(int nfd, fd_set *rfds, && pth_event_status(ev_timeout) == PTH_STATUS_OCCURRED) { selected = TRUE; /* POSIX.1-2001/SUSv3 compliance */ - if (rfds != NULL) FD_ZERO(rfds); - if (wfds != NULL) FD_ZERO(wfds); - if (efds != NULL) FD_ZERO(efds); + if (rfds != NULL) pth_util_fd_zero(nfd, rfds); + if (wfds != NULL) pth_util_fd_zero(nfd, wfds); + if (efds != NULL) pth_util_fd_zero(nfd, efds); rc = 0; } if (ev_extra != NULL && !selected) @@ -601,6 +630,7 @@ int pth_connect_ev(int s, const struct s int rv, err; socklen_t errlen; int fdmode; + int notfirsttry = 0; pth_implicit_init(); pth_debug2("pth_connect_ev: enter from thread \"%s\"", pth_current->name); @@ -615,8 +645,11 @@ int pth_connect_ev(int s, const struct s /* try to connect */ while ( (rv = pth_sc(connect)(s, (struct sockaddr *)addr, addrlen)) == -1 - && errno == EINTR) + && (errno == EINTR || errno == EINPROGRESS || errno == EALREADY)) + notfirsttry = 1; ; + if (rv == -1 && errno == EISCONN && notfirsttry) + rv = 0; /* restore filedescriptor mode */ pth_shield { pth_fdmode(s, fdmode); } @@ -624,6 +657,13 @@ int pth_connect_ev(int s, const struct s /* if it is still on progress wait until socket is really writeable */ if (rv == -1 && errno == EINPROGRESS && fdmode != PTH_FDMODE_NONBLOCK) { if ((ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_WRITEABLE|PTH_MODE_STATIC, &ev_key, s)) == NULL) + /* + * This will fail if the fd is > FD_SETSIZE so pass the error back to the + * caller. + */ + if (ev == NULL) { + return pth_error(-1, errno); + } return pth_error(-1, errno); if (ev_extra != NULL) pth_event_concat(ev, ev_extra, NULL);