OSSP CVS Repository

ossp - Check-in [2781]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 2781
Date: 2002-Nov-08 20:12:13 (local)
2002-Nov-08 19:12:13 (UTC)
User:rse
Branch:
Comment: Make pth_select(2) more compliant to POSIX.1-2001/SUSv3 select(2). This especially fixes the polling-only situation (timeout = (0,0)).
Tickets:
Inspections:
Files:
ossp-pkg/pth/ChangeLog      1.595 -> 1.596     4 inserted, 0 deleted
ossp-pkg/pth/pth_high.c      1.102 -> 1.103     46 inserted, 44 deleted

ossp-pkg/pth/ChangeLog 1.595 -> 1.596

--- ChangeLog    2002/11/08 16:17:47     1.595
+++ ChangeLog    2002/11/08 19:12:13     1.596
@@ -21,6 +21,10 @@
                   
   Changes between 2.0b0 and 2.0b1 (07-Nov-2002 to xx-Nov-2002)
 
+   *) Make pth_select(2) more compliant to POSIX.1-2001/SUSv3 select(2).
+      This especially fixes the polling-only situation (timeout = (0,0)).
+      [Ralf S. Engelschall]
+
    *) Make sure that in the even manager a polling-only select(2) call
       uses a correctly initialized timeout parameter.
       [Ralf S. Engelschall]


ossp-pkg/pth/pth_high.c 1.102 -> 1.103

--- pth_high.c   2002/11/08 16:20:15     1.102
+++ pth_high.c   2002/11/08 19:12:13     1.103
@@ -297,28 +297,27 @@
     pth_implicit_init();
     pth_debug2("pth_select_ev: called from thread \"%s\"", pth_current->name);
 
-    /* POSIX compliance */
+    /* POSIX.1-2001/SUSv3 compliance */
     if (nfd < 0 || nfd > FD_SETSIZE)
         return pth_error(-1, EINVAL);
     if (timeout != NULL) {
         if (   timeout->tv_sec  < 0
-            || timeout->tv_sec  > 100000000 /* about 3 years */
             || timeout->tv_usec < 0
-            || timeout->tv_usec >= 1000000  /* a full second */)
+            || timeout->tv_usec >= 1000000 /* a full second */)
             return pth_error(-1, EINVAL);
+        if (timeout->tv_sec > 31*24*60*60)
+            timeout->tv_sec = 31*24*60*60;
     }
 
     /* first deal with the special situation of a plain microsecond delay */
     if (nfd == 0 && rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) {
-        if (timeout->tv_sec < 0 || timeout->tv_usec < 0)
-            return pth_error(-1, EINVAL);
-        if (timeout->tv_sec == 0 && timeout->tv_usec < 500000) {
+        if (timeout->tv_sec == 0 && timeout->tv_usec <= 10000 /* 1/100 second */) {
             /* very small delays are acceptable to be performed directly */
             while (   pth_sc(select)(0, NULL, NULL, NULL, timeout) < 0
                    && errno == EINTR) ;
         }
         else {
-            /* larger delays have to use the scheduler */
+            /* larger delays have to go through the scheduler */
             ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key_timeout,
                            pth_timeout(timeout->tv_sec, timeout->tv_usec));
             if (ev_extra != NULL)
@@ -330,58 +329,57 @@
                     return pth_error(-1, EINTR);
             }
         }
-        /* POSIX compliance */
+        /* POSIX.1-2001/SUSv3 compliance */
         if (rfds != NULL) FD_ZERO(rfds);
         if (wfds != NULL) FD_ZERO(wfds);
         if (efds != NULL) FD_ZERO(efds);
         return 0;
     }
 
-    /* now directly poll filedescriptor sets to avoid unneccessary
+    /* now directly poll filedescriptor sets to avoid unnecessary
        (and resource consuming because of context switches, etc) event
        handling through the scheduler. We've to be carefully here, because not
-       all platforms guarranty us that the sets are unmodified if an error
-       or timeout occured. */
+       all platforms guaranty us that the sets are unmodified if an error
+       or timeout occurred. */
     delay.tv_sec  = 0;
     delay.tv_usec = 0;
     rtmp = NULL;
     if (rfds != NULL) {
-        rspare = *rfds;
+        memcpy(&rspare, rfds, sizeof(fd_set));
         rtmp = &rspare;
     }
     wtmp = NULL;
     if (wfds != NULL) {
-        wspare = *wfds;
+        memcpy(&wspare, wfds, sizeof(fd_set));
         wtmp = &wspare;
     }
     etmp = NULL;
     if (efds != NULL) {
-        espare = *efds;
+        memcpy(&espare, efds, sizeof(fd_set));
         etmp = &espare;
     }
-    while ((rc = pth_sc(select)(nfd, rtmp, wtmp, etmp, &delay)) < 0 && errno == EINTR) ;
-    if (rc > 0) {
+    while ((rc = pth_sc(select)(nfd, rtmp, wtmp, etmp, &delay)) < 0
+           && errno == EINTR)
+        ;
+    if (rc < 0)
+        /* pass-through immediate error */
+        return pth_error(-1, errno);
+    else if (   rc > 0
+             || (   rc == 0
+                 && timeout != NULL
+                 && pth_time_cmp(timeout, PTH_TIME_ZERO) == 0)) {
+        /* pass-through immediate success */
         if (rfds != NULL)
-            *rfds = rspare;
+            memcpy(rfds, &rspare, sizeof(fd_set));
         if (wfds != NULL)
-            *wfds = wspare;
+            memcpy(wfds, &wspare, sizeof(fd_set));
         if (efds != NULL)
-            *efds = espare;
+            memcpy(efds, &espare, sizeof(fd_set));
         return rc;
     }
-    if (rc == 0 && timeout != NULL) {
-        if (pth_time_cmp(timeout, PTH_TIME_ZERO) == 0) {
-            /* POSIX compliance */
-            if (rfds != NULL) FD_ZERO(rfds);
-            if (wfds != NULL) FD_ZERO(wfds);
-            if (efds != NULL) FD_ZERO(efds);
-            return 0;
-        }
-    }
-    if (rc < 0 && (errno == EINVAL || errno == EBADF))
-        return pth_error(-1, errno);
 
-    /* suspend current thread until one fd is ready or the timeout occurred */
+    /* suspend current thread until one filedescriptor
+       is ready or the timeout occurred */
     rc = -1;
     ev = ev_select = pth_event(PTH_EVENT_SELECT|PTH_MODE_STATIC,
                                &ev_key_select, &rc, nfd, rfds, wfds, efds);
@@ -394,25 +392,29 @@
     if (ev_extra != NULL)
         pth_event_concat(ev, ev_extra, NULL);
     pth_wait(ev);
+    if (ev_extra != NULL)
+        pth_event_isolate(ev_extra);
+    if (timeout != NULL)
+        pth_event_isolate(ev_timeout);
+
+    /* select return code semantics */
+    if (pth_event_status(ev_select) == PTH_STATUS_FAILED)
+        return pth_error(-1, EBADF);
     selected = FALSE;
-    pth_event_isolate(ev_select);
     if (pth_event_status(ev_select) == PTH_STATUS_OCCURRED)
         selected = TRUE;
-    if (timeout != NULL) {
-        pth_event_isolate(ev_timeout);
-        if (pth_event_status(ev_timeout) == PTH_STATUS_OCCURRED) {
-            selected = TRUE;
-            /* POSIX compliance */
-            if (rfds != NULL) FD_ZERO(rfds);
-            if (wfds != NULL) FD_ZERO(wfds);
-            if (efds != NULL) FD_ZERO(efds);
-            rc = 0;
-        }
+    if (   timeout != NULL
+        && 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);
+        rc = 0;
     }
-    if (pth_event_status(ev_select) == PTH_STATUS_FAILED)
-        return pth_error(-1, EBADF);
     if (ev_extra != NULL && !selected)
         return pth_error(-1, EINTR);
+
     return rc;
 }
 

CVSTrac 2.0.1