implementing IN_PROGRESS

Havoc Pennington hp at redhat.com
Sat Feb 25 13:34:55 PST 2006


On Sat, 2006-02-25 at 21:40 +0100, Thiago Macieira wrote:
> * no modification to the dispatch lock
> * when calling to user (binding) code, the binding has the option to 
> return HANDLED, NOT_HANDLED and (new one) PARTIALLY_HANDLED.
> * when receiving a PARTIALLY_HANDLED return code, the code would pop
> the 
> message from the queue just as if it had been fully handled and place
> it 
> in a new queue, allocated on the stack, local to the function.
> * after all other locks have been released, call the binding again for
> all 
> the PARTIALLY_HANDLED messages. There is no return code: the binding
> MUST 
> handle it fully. 

But the dispatch lock won't be released while the partially handled
messages are on the stack - it can only be released when the current
call stack unwinds all the way back to the app handler. What am I
missing?

Here's the "normal case":

   BindingMainLoopIterate
     calls dbus_connection_dispatch (TAKES DISPATCH LOCK)
       calls binding code to handle a message
         calls application code associated with the message
     (DROPS DISPATCH LOCK)
   BindingMainLoopIterate
     ... repeats

Here's the bug:

   BindingMainLoopIterate
     calls dbus_connection_dispatch (TAKES DISPATCH LOCK)
       calls binding code to handle a message
         calls application code associated with the message
           calls BindingMainLoopIterate [1] 
             calls dbus_connection_dispatch (DEADLOCKS ON DISPATCH LOCK)

I understand you to be saying:

   BindingMainLoopIterate
     calls dbus_connection_dispatch (TAKES DISPATCH LOCK)
       calls binding code to handle a message (SAVES A RECURSION FLAG)
         calls application code associated with the message
           calls BindingMainLoopIterate [1] 
             calls dbus_connection_dispatch or similar
               calls binding to handle a message
                 returns PARTIALLY_HANDLED since recursion flag set
               waits for dispatch lock to be dropped [2]
               calls binding to handle PARTIALLY_HANDLED messages

My proposal is:

   BindingMainLoopIterate
     calls dbus_connection_dispatch (TAKES DISPATCH LOCK)
       calls binding code to handle a message
         calls application code associated with the message
           calls BindingMainLoopIterate [1]
             calls dbus_connection_dispatch or similar
	       if dispatch lock held by another thread:
                 (not possible with this call stack, 
                  since we hold it in this thread)
               else:
                 return IN_PROGRESS or COMPLETED, do nothing
     (DROPS DISPATCH LOCK)
   BindingMainLoopIterate
     ... this would look like the "normal case" above
             
[1]
the "calls BindingMainLoopIterate" could also be a direct call to any of
the DBusConnection methods that take the dispatch lock and it would
deadlock with today's libdbus.

This is probably the answer to my question in my last mail about why
block_pending_call() doesn't take the dispatch lock - it would deadlock
in this case. I guess maybe we could say the dispatch lock doesn't cover
the whole message queue, only the "current" message, but I still suspect
the locking is a bit off.

[2]
this is where I don't understand your proposal - I don't think the
dispatch lock is ever dropped.

Havoc




More information about the dbus mailing list