From 1ea5d42dc058044af3a9ba4b9da62bf4569d54b5 Mon Sep 17 00:00:00 2001 From: "John (J5) Palmieri" Date: Wed, 31 Aug 2005 02:18:43 +0000 Subject: * python/dbus_bindings.pyx (_pending_call_notification, cunregister_function_handler, cmessage_function_handler): All callback functions have been rearranged to workaround a bug in Pyrex when working with the GIL which is Python's global lock when dealing with threads. They have been split into a wrapper function (which assumes the name of the old function) and a _GIL_safe_ function which contains the functionality of the old function. This ensures that Pyrex does not write code the lock is released. --- ChangeLog | 13 ++++++ python/dbus_bindings.pyx | 110 ++++++++++++++++++++++++++++------------------- 2 files changed, 78 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index c36be7ee..de2b50b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2005-08-30 John (J5) Palmieri + + * python/dbus_bindings.pyx + (_pending_call_notification, cunregister_function_handler, + cmessage_function_handler): All callback functions have been rearranged + to workaround a bug in Pyrex when working with the GIL which is Python's + global lock when dealing with threads. They have been split into + a wrapper function (which assumes the name of the old function) and + a _GIL_safe_ function which contains the functionality + of the old function. This ensures that Pyrex does not write code + the lock is released. + + 2005-08-30 John (J5) Palmieri * python/dbus_bindings.pyx (_pending_call_notification): Obtain the diff --git a/python/dbus_bindings.pyx b/python/dbus_bindings.pyx index 6973944a..2871ae8c 100644 --- a/python/dbus_bindings.pyx +++ b/python/dbus_bindings.pyx @@ -178,52 +178,67 @@ cdef class PendingCall cdef class Watch cdef class MessageIter +cdef void _GIL_safe_cunregister_function_handler (DBusConnection *connection, + void *user_data): + cdef Connection conn + + itup = user_data + assert (type(tup) == list) + function = tup[1] + conn = Connection() + conn.__cinit__(None, connection) + + args = (conn) + function(*args) + cdef void cunregister_function_handler (DBusConnection *connection, void *user_data): - cdef Connection conn cdef PyGILState_STATE gil - gil = PyGILState_Ensure() try: - itup = user_data - assert (type(tup) == list) - function = tup[1] - conn = Connection() - conn.__cinit__(None, connection) - - args = [conn] - function(*args) + _GIL_safe_cunregister_function_handler (connection, user_data); finally: PyGILState_Release(gil) -cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection, + + +cdef DBusHandlerResult _GIL_safe_cmessage_function_handler ( + DBusConnection *connection, DBusMessage *msg, void *user_data): cdef Connection conn cdef Message message - cdef PyGILState_STATE gil + tup = user_data + assert (type(tup) == list) + function = tup[0] + message = EmptyMessage() + + #we don't own the message so we need to ref it + dbus_message_ref(msg) + message._set_msg(msg) + conn = Connection() + conn.__cinit__(None, connection) + args = (conn, + message) + + retval = function(*args) + + if (retval == None): + retval = DBUS_HANDLER_RESULT_HANDLED + return retval + +cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection, + DBusMessage *msg, + void *user_data): + cdef PyGILState_STATE gil gil = PyGILState_Ensure() try: - tup = user_data - assert (type(tup) == list) - function = tup[0] - message = EmptyMessage() - - #we don't own the message so we need to ref it - dbus_message_ref(msg) - message._set_msg(msg) - conn = Connection() - conn.__cinit__(None, connection) - args = [conn, - message] - retval = function(*args) - if (retval == None): - retval = DBUS_HANDLER_RESULT_HANDLED - return retval + return _GIL_safe_cmessage_function_handler (connection, msg, user_data); finally: PyGILState_Release(gil) + cdef class Connection: def __init__(self, address=None, Connection _conn=None): cdef DBusConnection *c_conn @@ -487,11 +502,11 @@ cdef class Connection: return child_entries -cdef void _pending_call_notification(DBusPendingCall *pending_call, void *user_data): +cdef void _GIL_safe_pending_call_notification (DBusPendingCall *pending_call, + void *user_data): cdef DBusMessage *dbus_message cdef Message message - cdef PyGILState_STATE gil - + (reply_handler, error_handler) = user_data dbus_message = dbus_pending_call_steal_reply(pending_call) @@ -500,25 +515,30 @@ cdef void _pending_call_notification(DBusPendingCall *pending_call, void *user_d type = message.get_type() - gil = PyGILState_Ensure() - try: - if type == MESSAGE_TYPE_METHOD_RETURN: - args = message.get_args_list() - reply_handler(*args) - elif type == MESSAGE_TYPE_ERROR: - args = message.get_args_list() - if len(args) > 0: - error_handler(DBusException(args[0])) - else: - error_handler(DBusException("")) + if type == MESSAGE_TYPE_METHOD_RETURN: + args = message.get_args_list() + reply_handler(*args) + elif type == MESSAGE_TYPE_ERROR: + args = message.get_args_list() + if len(args) > 0: + error_handler(DBusException(args[0])) else: - error_handler(DBusException('Unexpected Message Type: ' + message.type_to_name(type))) - finally: - PyGILState_Release(gil) + error_handler(DBusException("")) + else: + error_handler(DBusException('Unexpected Message Type: ' + message.type_to_name(type))) dbus_message_unref(dbus_message) dbus_pending_call_unref(pending_call) +cdef void _pending_call_notification(DBusPendingCall *pending_call, + void *user_data): + cdef PyGILState_STATE gil + gil = PyGILState_Ensure() + try: + _GIL_safe_pending_call_notification (pending_call, user_data); + finally: + PyGILState_Release(gil) + cdef void _pending_call_free_user_data(void *data): call_tuple = data Py_XDECREF(call_tuple) -- cgit