[PATCH] Have pending call keep a ref to its connection (fixes
the NetworkManager crash)
Havoc Pennington
hp at redhat.com
Wed Jul 12 19:10:28 PDT 2006
John (J5) Palmieri wrote:
> @@ -3734,6 +3734,10 @@
> "Disconnected"))
> {
> _dbus_bus_check_connection_and_unref (connection);
> +
> + /* remove all active pending calls */
> + _dbus_hash_table_remove_all (connection->pending_replies);
> +
Here we just delete the pending calls. But it might be nicer to call the
notify on all of them, with an error message, don't you think?
Then people blocking on a pending call don't have to also watch for
disconnection - the pending call notifier is guaranteed to be called.
One way to do this; in the place that currently queues the
disconnect_message_link, also cancel all the pending call timeouts and
queue all the timeout errors, then queue the disconnect_message_link.
Then, be sure we warn or otherwise prevent adding new pending calls
while disconnected.
This should guarantee that no pending calls remain in the point above
(when processing the disconnected message) since it guarantees that
there's always a reply to all pending calls, before the disconnect
message arrives.
Does this make sense? I'm not sure I thought about all the angles.
>
> _dbus_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1);
>
> + if (connection != NULL && !dbus_connection_get_is_connected (connection))
> + return NULL;
> +
Is calling this with a null connection really allowed? What does it mean
in that case?
I think the above get_is_connected() might make more sense as an
assertion/warning here, and have dbus-connection.c not call this
function if it's not connected.
It looks to me like dbus_connection_send_with_reply() needs more thought
about what happens if it's called while disconnected. The options:
- it's a return_if_fail - callers must check this (seems painful
for app developers, also could not be checked in a threadsafe
way)
- it silently does nothing - doesn't really work since it returns
the pending call object, and we'd have none to return
- it creates a pending call and immediately times it out - but
this is a disaster since it doesn't make sense to queue error
replies after disconnected is already received
- we add a DBusError and throw an error if you call while
disconnected... but this sounds like an annoying api break
and most people would just ignore the error
- we return a pending call with an error reply already set...
but then when is the notify function called? synchronously
when it gets set?
my best thought right now is that we return TRUE (had enough memory) but
return NULL for the pending call? But existing apps might crash in that
case.
I'm not sure this works at all for existing apps right now - pending
calls returned after disconnect might do something nasty like block
forever even??? Or maybe something sane happens to work out?
> if (timeout_milliseconds == -1)
> timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
>
> @@ -119,8 +122,12 @@
>
> pending->refcount.value = 1;
> pending->connection = connection;
> + if (pending->connection != NULL)
> + dbus_connection_ref (pending->connection);
> +
(same here about null connection not allowed?)
Hmm. Maybe set up a test case for calling send_with_reply after
disconnect, and see what happens right now and then we can also verify
the new behavior we decide is right...
Havoc
More information about the dbus
mailing list