pkgsrc/devel/pth/patches/patch-ac
drochner 3ca131bd2b deal with connect(2) returning EINPROGRESS/EALREADY/EISCONN on non-blocking
sockets (allowed by POSIX, but apparently not done usually on other OSes)
bump PKGREVISION
2010-08-06 19:21:26 +00:00

137 lines
4.8 KiB
Text

$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);