OSSP CVS Repository

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

Check-in Number: 1654
Date: 2002-Jan-27 11:47:01 (local)
2002-Jan-27 10:47:01 (UTC)
User:rse
Branch:
Comment: Replaced thread-unsafe usage of a static struct iovec in pth_writev_ev() with a thread-safe stack/heap-based solution.

Submitted by: Mark Burton <markb@ordern.com>

Tickets:
Inspections:
Files:
ossp-pkg/pth/pth_high.c      1.79 -> 1.80     26 inserted, 7 deleted

ossp-pkg/pth/pth_high.c 1.79 -> 1.80

--- pth_high.c   2001/07/30 18:47:28     1.79
+++ pth_high.c   2002/01/27 10:47:01     1.80
@@ -860,6 +860,9 @@
     ssize_t rv;
     ssize_t s;
     int n;
+    struct iovec tiov_stack[32];
+    struct iovec *tiov;
+    int tiovcnt;
 
     pth_implicit_init();
     pth_debug2("pth_writev_ev: enter from thread \"%s\"", pth_current->name);
@@ -873,6 +876,16 @@
 
     /* poll filedescriptor if not already in non-blocking operation */
     if (fdmode != PTH_FDMODE_NONBLOCK) {
+        /* provide temporary iovec structure */
+        if (iovcnt > sizeof(tiov_stack)) {
+            tiovcnt = (sizeof(struct iovec) * UIO_MAXIOV);
+            if ((tiov = (struct iovec *)malloc(tiovcnt)) == NULL)
+                return -1 /* errno is set */;
+        }
+        else {
+            tiovcnt = sizeof(tiov_stack);
+            tiov    = tiov_stack;
+        }
 
         /* init return value and number of bytes to write */
         rv      = 0;
@@ -881,7 +894,7 @@
         /* init local iovec structure */
         liov    = NULL;
         liovcnt = 0;
-        pth_writev_iov_advance(iov, iovcnt, 0, &liov, &liovcnt);
+        pth_writev_iov_advance(iov, iovcnt, 0, &liov, &liovcnt, tiov, tiovcnt);
 
         /* first directly poll filedescriptor for writeability
            to avoid unneccessary (and resource consuming because of context
@@ -905,6 +918,8 @@
                     pth_event_isolate(ev);
                     if (!pth_event_occurred(ev)) {
                         pth_fdmode(fd, fdmode);
+                        if (iovcnt > sizeof(tiov_stack))
+                            free(tiov);
                         return_errno(-1, EINTR);
                     }
                 }
@@ -926,7 +941,7 @@
                we've to mimic the usual blocking I/O behaviour of writev(2) */
             if (s > 0 && s < (ssize_t)nbytes) {
                 nbytes -= s;
-                pth_writev_iov_advance(iov, iovcnt, s, &liov, &liovcnt);
+                pth_writev_iov_advance(iov, iovcnt, s, &liov, &liovcnt, tiov, tiovcnt);
                 n = 0;
                 continue;
             }
@@ -938,6 +953,10 @@
             /* stop looping */
             break;
         }
+
+        /* cleanup */
+        if (iovcnt > sizeof(tiov_stack))
+            free(tiov);
     }
     else {
         /* just perform the actual write operation */
@@ -974,9 +993,9 @@
 
 /* advance the virtual pointer of a struct iov */
 intern void pth_writev_iov_advance(const struct iovec *riov, int riovcnt, size_t advance,
-                                   struct iovec **liov, int *liovcnt)
+                                   struct iovec **liov, int *liovcnt, 
+                                   struct iovec *tiov, int tiovcnt)
 {
-    static struct iovec siov[UIO_MAXIOV];
     int i;
 
     if (*liov == NULL && *liovcnt == 0) {
@@ -987,10 +1006,10 @@
     if (advance > 0) {
         if (*liov == riov && *liovcnt == riovcnt) {
             /* reinitialize with a copy to be able to adjust it */
-            *liov = &siov[0];
+            *liov = &tiov[0];
             for (i = 0; i < riovcnt; i++) {
-                siov[i].iov_base = riov[i].iov_base;
-                siov[i].iov_len  = riov[i].iov_len;
+                tiov[i].iov_base = riov[i].iov_base;
+                tiov[i].iov_len  = riov[i].iov_len;
             }
         }
         /* advance the virtual pointer */

CVSTrac 2.0.1