Author: tross
Date: Fri Dec  5 21:03:47 2014
New Revision: 1643431

URL: http://svn.apache.org/r1643431
Log:
DISPATCH-78 - Fixed a thread-safety violation in the driver related to failed 
connections.
              This fixes the problem outlined in the Jira.

Modified:
    qpid/dispatch/trunk/include/qpid/dispatch/driver.h
    qpid/dispatch/trunk/src/posix/driver.c
    qpid/dispatch/trunk/src/server.c

Modified: qpid/dispatch/trunk/include/qpid/dispatch/driver.h
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/driver.h?rev=1643431&r1=1643430&r2=1643431&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/driver.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/driver.h Fri Dec  5 21:03:47 2014
@@ -330,6 +330,9 @@ void qdpn_connector_close(qdpn_connector
  */
 bool qdpn_connector_closed(qdpn_connector_t *connector);
 
+bool qdpn_connector_failed(qdpn_connector_t *connector);
+
+
 /** Destructor for the given connector.
  *
  * Assumes the connector's socket has been closed prior to call.

Modified: qpid/dispatch/trunk/src/posix/driver.c
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/posix/driver.c?rev=1643431&r1=1643430&r2=1643431&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/posix/driver.c (original)
+++ qpid/dispatch/trunk/src/posix/driver.c Fri Dec  5 21:03:47 2014
@@ -97,6 +97,7 @@ struct qdpn_connector_t {
     bool pending_tick;
     bool pending_read;
     bool pending_write;
+    bool socket_error;
     bool closed;
     bool input_done;
     bool output_done;
@@ -351,6 +352,7 @@ qdpn_connector_t *qdpn_connector_fd(qdpn
     c->pending_tick = false;
     c->pending_read = false;
     c->pending_write = false;
+    c->socket_error = false;
     c->name[0] = '\0';
     c->idx = 0;
     c->fd = fd;
@@ -455,8 +457,10 @@ void qdpn_connector_close(qdpn_connector
     ctor->status = 0;
     if (close(ctor->fd) == -1)
         perror("close");
-    ctor->closed = true;
-    ctor->driver->closed_count++;
+    if (!ctor->closed) {
+        ctor->closed = true;
+        ctor->driver->closed_count++;
+    }
 }
 
 bool qdpn_connector_closed(qdpn_connector_t *ctor)
@@ -464,6 +468,11 @@ bool qdpn_connector_closed(qdpn_connecto
     return ctor ? ctor->closed : true;
 }
 
+bool qdpn_connector_failed(qdpn_connector_t *ctor)
+{
+    return ctor ? ctor->socket_error : true;
+}
+
 void qdpn_connector_free(qdpn_connector_t *ctor)
 {
     if (!ctor) return;
@@ -775,7 +784,7 @@ int qdpn_driver_wait_3(qdpn_driver_t *d)
             c->pending_write = (idx && d->fds[idx].revents & POLLOUT);
             c->pending_tick = (c->wakeup &&  c->wakeup <= now);
             if (idx && d->fds[idx].revents & POLLERR)
-                qdpn_connector_close(c);
+                c->socket_error = true;
             else if (idx && (d->fds[idx].revents & POLLHUP)) {
                 if (c->trace & (PN_TRACE_FRM | PN_TRACE_RAW | PN_TRACE_DRV)) {
                     fprintf(stderr, "hangup on connector %s\n", c->name);
@@ -847,9 +856,8 @@ qdpn_connector_t *qdpn_driver_connector(
         qdpn_connector_t *c = d->connector_next;
         d->connector_next = DEQ_NEXT(c);
 
-        if (c->closed || c->pending_read || c->pending_write || 
c->pending_tick) {
+        if (c->closed || c->pending_read || c->pending_write || 
c->pending_tick || c->socket_error)
             return c;
-        }
     }
 
     return NULL;

Modified: qpid/dispatch/trunk/src/server.c
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/server.c?rev=1643431&r1=1643430&r2=1643431&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/server.c (original)
+++ qpid/dispatch/trunk/src/server.c Fri Dec  5 21:03:47 2014
@@ -535,7 +535,12 @@ static void *thread_run(void *arg)
         // Process the connector that we now have exclusive access to.
         //
         if (cxtr) {
-            int work_done = process_connector(qd_server, cxtr);
+            int work_done = 1;
+
+            if (qdpn_connector_failed(cxtr))
+                qdpn_connector_close(cxtr);
+            else
+                work_done = process_connector(qd_server, cxtr);
 
             //
             // Check to see if the connector was closed during processing



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to