Author: aconway
Date: Fri Oct 24 15:08:10 2014
New Revision: 1634072

URL: http://svn.apache.org/r1634072
Log:
DISPATCH-72: Fix c_entity locking to prevent add/remove entities during update.

Modified:
    qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py
    qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
    qpid/dispatch/trunk/router/src/main.c
    qpid/dispatch/trunk/src/c_entity.c

Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py Fri Oct 24 
15:08:10 2014
@@ -20,7 +20,6 @@
 """Access to functions in libqpid-dispatch.so"""
 
 import ctypes
-from contextlib import contextmanager
 from ctypes import c_char_p, c_long, py_object
 from qpid_dispatch.site import QPID_DISPATCH_LIB
 
@@ -71,15 +70,8 @@ class QdDll(ctypes.PyDLL):
 
         self._prototype(self.qd_connection_manager_start, None, 
[self.qd_dispatch_p])
         self._prototype(self.qd_waypoint_activate_all, None, 
[self.qd_dispatch_p])
-        self._prototype(self.qd_c_entity_flush, c_long, [py_object])
-
-    @contextmanager
-    def scoped_dispatch_router_lock(self, dispatch):
-        self.qd_dispatch_router_lock(dispatch)
-        try:
-            yield
-        finally:
-            self.qd_dispatch_router_unlock(dispatch)
+        self._prototype(self.qd_c_entity_update_begin, c_long, [py_object])
+        self._prototype(self.qd_c_entity_update_end, None, [])
 
     def _errcheck(self, result, func, args):
         if self.qd_error_code():

Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py 
(original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py Fri 
Oct 24 15:08:10 2014
@@ -309,8 +309,10 @@ class EntityCache(object):
                 except KeyError: pass
 
 
-        with self.qd.scoped_dispatch_router_lock(self.agent.dispatch):
-            self.qd.qd_c_entity_flush(events)
+        # FIXME aconway 2014-10-23: locking is ugly, push it down into C code.
+        self.qd.qd_dispatch_router_lock(self.agent.dispatch)
+        try:
+            self.qd.qd_c_entity_update_begin(events)
             # Collapse sequences of add/remove into a single 
remove/add/remove_add per pointer.
             actions = {}
             for action, type, pointer in events:
@@ -326,7 +328,9 @@ class EntityCache(object):
                     self.add(entity, pointer)
 
             for e in self.entities: e._update()
-
+        finally:
+            self.qd.qd_c_entity_update_end()
+            self.qd.qd_dispatch_router_unlock(self.agent.dispatch)
 
 class Agent(object):
     """AMQP managment agent"""

Modified: qpid/dispatch/trunk/router/src/main.c
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/router/src/main.c?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/router/src/main.c (original)
+++ qpid/dispatch/trunk/router/src/main.c Fri Oct 24 15:08:10 2014
@@ -113,7 +113,10 @@ static void main_process(const char *con
     }
 
     qd_server_run(dispatch);
-    qd_dispatch_free(dispatch);
+
+    qd_dispatch_t *d = dispatch;
+    dispatch = NULL;
+    qd_dispatch_free(d);
 
     if (exit_with_sigint) {
         signal(SIGINT, SIG_DFL);

Modified: qpid/dispatch/trunk/src/c_entity.c
URL: 
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/c_entity.c?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/c_entity.c (original)
+++ qpid/dispatch/trunk/src/c_entity.c Fri Oct 24 15:08:10 2014
@@ -70,8 +70,11 @@ void qd_c_entity_add(const char *type, v
 
 void qd_c_entity_remove(const char *type, void *object) { push_event(REMOVE, 
type, object); }
 
-// Flush events in the add/remove cache into a python list of (action, type, 
pointer)
-qd_error_t qd_c_entity_flush(PyObject *list) {
+// Get events in the add/remove cache into a python list of (action, type, 
pointer)
+// Locks the entity cache so entities can be updated safely (prevent entities 
from being deleted.)
+// Do not processs any entities if return error code != 0
+// Must call qd_c_entity_update_end when done, regardless of error code.
+qd_error_t qd_c_entity_update_begin(PyObject *list) {
     if (!event_lock) return QD_ERROR_NONE;    /* Unit tests don't call 
qd_c_entity_initialize */
     qd_error_clear();
     sys_mutex_lock(event_lock);
@@ -86,10 +89,13 @@ qd_error_t qd_c_entity_flush(PyObject *l
         free(event);
         event = DEQ_HEAD(event_list);
     }
-    sys_mutex_unlock(event_lock);
     return qd_error_code();
 }
 
+void qd_c_entity_update_end() {
+    sys_mutex_unlock(event_lock);
+}
+
 const char *QD_ALLOCATOR_TYPE = "allocator";
 const char *QD_CONNECTION_TYPE = "connection";
 const char *QD_ROUTER_TYPE = "router";



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

Reply via email to