You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by rj...@apache.org on 2015/05/23 14:24:19 UTC

svn commit: r1681338 - in /tomcat/native/trunk/native: include/tcn.h src/poll.c

Author: rjung
Date: Sat May 23 12:24:19 2015
New Revision: 1681338

URL: http://svn.apache.org/r1681338
Log:
Forward port lots of xies to poll.c from 1.1 to trunk:

r1667243 | markt | 2015-03-17 11:28:05 +0100 (Tue, 17 Mar 2015) | 1 line
Follow-up to r1665888. Review by kkolinko. else clause should not depend on s->pe

r1665888 | markt | 2015-03-11 15:44:23 +0100 (Wed, 11 Mar 2015) | 1 line
Fix 57653. Crash when multiple events for same socket are returned via separate apr_pollfd_t structures

r1525525 | rjung | 2013-09-23 10:08:56 +0200 (Mon, 23 Sep 2013) | 6 lines
Change return code when removing a socket from a poller, that was
actually not in the poller from APR_SUCCESS to APR_NOTFOUND.
This lead to corrupt poller handling in the Tomcat APR connector,
at least sporadically on Solaris Sparc.

r1441792 | mturk | 2013-02-02 20:25:49 +0100 (Sat, 02 Feb 2013) | 1 line
Fix BZ55413 by ensuring the returned value is number of event/sockets pairs

r1414562 | mturk | 2012-11-28 08:28:20 +0100 (Wed, 28 Nov 2012) | 1 line
Fix typo in --enable-maintainer-mode

r1414560 | mturk | 2012-11-28 08:19:46 +0100 (Wed, 28 Nov 2012) | 1 line
Limit socket to a single instance in the pollset. This allows to optimize remove loop - actually remove it.

Modified:
    tomcat/native/trunk/native/include/tcn.h
    tomcat/native/trunk/native/src/poll.c

Modified: tomcat/native/trunk/native/include/tcn.h
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/include/tcn.h?rev=1681338&r1=1681337&r2=1681338&view=diff
==============================================================================
--- tomcat/native/trunk/native/include/tcn.h (original)
+++ tomcat/native/trunk/native/include/tcn.h Sat May 23 12:24:19 2015
@@ -156,6 +156,7 @@ struct tcn_socket_t {
     char         *jsbbuff;
     char         *jrbbuff;
     tcn_nlayer_t *net;
+    tcn_pfde_t   *pe;
     apr_time_t          last_active;
     apr_interval_time_t timeout;
 };

Modified: tomcat/native/trunk/native/src/poll.c
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/poll.c?rev=1681338&r1=1681337&r2=1681338&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/poll.c (original)
+++ tomcat/native/trunk/native/src/poll.c Sat May 23 12:24:19 2015
@@ -216,6 +216,14 @@ static apr_status_t do_add(tcn_pollset_t
 #endif
         return APR_ENOMEM;
     }
+    if (s->pe != NULL) {
+        /* Socket is already added to the pollset.
+         */
+#ifdef TCN_DO_STATISTICS
+        p->sp_equals++;
+#endif
+        return APR_EEXIST;
+    }
     if (timeout == TCN_NO_SOCKET_TIMEOUT) {
         timeout = p->default_timeout;
     }
@@ -246,6 +254,7 @@ static apr_status_t do_add(tcn_pollset_t
     }
     else {
         APR_RING_INSERT_TAIL(&p->poll_ring, elem, tcn_pfde_t, link);
+        s->pe = elem;
     }
     return rv;
 }
@@ -275,44 +284,21 @@ TCN_IMPLEMENT_CALL(jint, Poll, addWithTi
     return (jint) do_add(p, s, (apr_int16_t)reqevents, J2T(socket_timeout));
 }
 
-static apr_status_t do_remove(tcn_pollset_t *p, const apr_pollfd_t *fd)
-{
-    apr_status_t rv;
-    tcn_pfde_t  *ep;
-
-    rv = apr_pollset_remove(p->pollset, fd);
-    APR_RING_FOREACH(ep, &p->poll_ring, tcn_pfde_t, link)
-    {
-        if (fd->desc.s == ep->fd.desc.s) {
-            APR_RING_REMOVE(ep, link);
-            APR_RING_INSERT_TAIL(&p->dead_ring, ep, tcn_pfde_t, link);
-            p->nelts--;
-#ifdef TCN_DO_STATISTICS
-            p->sp_removed++;
-#endif
-            break;
-        }
-    }
-    return rv;
-}
-
-static void update_last_active(tcn_pollset_t *p, const apr_pollfd_t *fd, apr_time_t t)
-{
-    tcn_socket_t *s = (tcn_socket_t *)fd->client_data;
-    TCN_ASSERT(s != 0);
-    s->last_active = t;
-}
-
 TCN_IMPLEMENT_CALL(jint, Poll, remove)(TCN_STDARGS, jlong pollset,
                                        jlong socket)
 {
     apr_pollfd_t fd;
+    apr_status_t rv;
     tcn_pollset_t *p = J2P(pollset,  tcn_pollset_t *);
-    tcn_socket_t *s  = J2P(socket, tcn_socket_t *);
+    tcn_socket_t  *s = J2P(socket, tcn_socket_t *);
 
     UNREFERENCED_STDARGS;
     TCN_ASSERT(socket != 0);
 
+    if (s->pe == NULL) {
+        /* Already removed */
+        return APR_NOTFOUND;
+    }
     fd.desc_type   = APR_POLL_SOCKET;
     fd.desc.s      = s->sock;
     fd.client_data = s;
@@ -321,7 +307,15 @@ TCN_IMPLEMENT_CALL(jint, Poll, remove)(T
     p->sp_remove++;
 #endif
 
-    return (jint)do_remove(p, &fd);
+    rv = apr_pollset_remove(p->pollset, &fd);
+    APR_RING_REMOVE(s->pe, link);
+    APR_RING_INSERT_TAIL(&p->dead_ring, s->pe, tcn_pfde_t, link);
+    s->pe = NULL;
+    p->nelts--;
+#ifdef TCN_DO_STATISTICS
+    p->sp_removed++;
+#endif
+    return rv;
 }
 
 
@@ -350,8 +344,7 @@ TCN_IMPLEMENT_CALL(jint, Poll, poll)(TCN
         APR_RING_FOREACH(ep, &p->poll_ring, tcn_pfde_t, link)
         {
             apr_interval_time_t socket_timeout = 0;
-            tcn_socket_t *s;
-            s = (tcn_socket_t *)ep->fd.client_data;
+            tcn_socket_t *s = (tcn_socket_t *)ep->fd.client_data;
             if (s->timeout == TCN_NO_SOCKET_TIMEOUT) {
                 socket_timeout = p->default_timeout;
             }
@@ -402,12 +395,33 @@ TCN_IMPLEMENT_CALL(jint, Poll, poll)(TCN
         if (!remove)
             now = apr_time_now();
         for (i = 0; i < num; i++) {
+            tcn_socket_t *s = (tcn_socket_t *)fd->client_data;
             p->set[i*2+0] = (jlong)(fd->rtnevents);
-            p->set[i*2+1] = P2J(fd->client_data);
-            if (remove)
-                do_remove(p, fd);
-            else
-                update_last_active(p, fd, now);
+            p->set[i*2+1] = P2J(s);
+            /* If a socket is registered for multiple events and the poller has
+               multiple events to return it may do as a single pair in this
+               array or as multiple pairs depending on implementation. On OSX at
+               least, multiple pairs have been observed. In this case do not try
+               and remove socket from the pollset for a second time else a crash
+               will result. */ 
+            if (remove) {
+                if (s->pe) {
+                    apr_pollset_remove(p->pollset, fd);
+                    APR_RING_REMOVE(s->pe, link);
+                    APR_RING_INSERT_TAIL(&p->dead_ring, s->pe, tcn_pfde_t, link);
+                    s->pe = NULL;
+                    p->nelts--;
+#ifdef TCN_DO_STATISTICS
+                    p->sp_removed++;
+#endif
+                }
+            }
+            else {
+                /* Update last active with the current time
+                 * after the poll call.
+                 */
+                s->last_active = now;
+            }
             fd ++;
         }
         (*e)->SetLongArrayRegion(e, set, 0, num * 2, p->set);
@@ -443,31 +457,35 @@ TCN_IMPLEMENT_CALL(jint, Poll, maintain)
         }
         if ((now - s->last_active) >= timeout) {
             p->set[num++] = P2J(s);
-            APR_RING_REMOVE(ep, link);
-            APR_RING_INSERT_TAIL(&p->dead_ring, ep, tcn_pfde_t, link);
-            p->nelts--;
+            if (remove) {
+                APR_RING_REMOVE(ep, link);
+                APR_RING_INSERT_TAIL(&p->dead_ring, ep, tcn_pfde_t, link);
+                s->pe = NULL;
+                p->nelts--;
 #ifdef TCN_DO_STATISTICS
-            p->sp_removed++;
+                p->sp_removed++;
 #endif
+            }
         }
     }
-    if (remove && num) {
+    if (num) {
 #ifdef TCN_DO_STATISTICS
-         p->sp_maintained += num;
-         p->sp_max_maintained = TCN_MAX(p->sp_max_maintained, num);
+        p->sp_maintained += num;
+        p->sp_max_maintained = TCN_MAX(p->sp_max_maintained, num);
 #endif
-        for (i = 0; i < num; i++) {
-            apr_pollfd_t fd;
-            tcn_socket_t *s = J2P(p->set[i], tcn_socket_t *);
-            fd.desc_type    = APR_POLL_SOCKET;
-            fd.desc.s       = s->sock;
-            fd.client_data  = s;
-            fd.reqevents    = APR_POLLIN | APR_POLLOUT;
-            apr_pollset_remove(p->pollset, &fd);
+        if (remove) {
+            for (i = 0; i < num; i++) {
+                apr_pollfd_t fd;
+                tcn_socket_t *s = J2P(p->set[i], tcn_socket_t *);
+                fd.desc_type    = APR_POLL_SOCKET;
+                fd.desc.s       = s->sock;
+                fd.client_data  = s;
+                fd.reqevents    = APR_POLLIN | APR_POLLOUT;
+                apr_pollset_remove(p->pollset, &fd);
+            }
         }
-    }
-    if (num)
         (*e)->SetLongArrayRegion(e, set, 0, num, p->set);
+    }
     return (jint)num;
 }
 
@@ -505,7 +523,7 @@ TCN_IMPLEMENT_CALL(jint, Poll, pollset)(
     }
     if (n > 0)
         (*e)->SetLongArrayRegion(e, set, 0, n, p->set);
-    return n;
+    return n / 2;
 }
 
 TCN_IMPLEMENT_CALL(jboolean, Poll, wakeable)(TCN_STDARGS, jlong pollset)



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org