<pre>So I've been debugging a randomly occurring "Out of Memory" error. In my trace of what is happening in my multithreaded program, I have come across this function below as my problem.<br><br>static dbus_bool_t
<br>protected_change_timeout (DBusConnection *connection,<br> DBusTimeout *timeout,<br> DBusTimeoutAddFunction add_function,<br> DBusTimeoutRemoveFunction remove_function,
<br> DBusTimeoutToggleFunction toggle_function,<br> dbus_bool_t enabled)<br>{<br> DBusTimeoutList *timeouts;<br> dbus_bool_t retval;<br> <br> HAVE_LOCK_CHECK (connection);
<br><br> /* This isn't really safe or reasonable; a better pattern is the "do everything, then<br> * drop lock and call out" one; but it has to be propagated up through all callers<br> */<br> <br> timeouts = connection->timeouts;
<br> if (timeouts)<br> {<br> connection->timeouts = NULL;<br> _dbus_connection_ref_unlocked (connection);<br> CONNECTION_UNLOCK (connection);<br><br> if (add_function)<br> retval = (* add_function) (timeouts, timeout);
<br> else if (remove_function)<br> {<br> retval = TRUE;<br> (* remove_function) (timeouts, timeout);<br> }<br> else<br> {<br> retval = TRUE;<br> (* toggle_function) (timeouts, timeout, enabled);
<br> }<br> <br> CONNECTION_LOCK (connection);<br> connection->timeouts = timeouts;<br> _dbus_connection_unref_unlocked (connection);<br><br> return retval;<br> }<br> else<br> return FALSE;
<br>}
<br>Apparently DBus sets the timeout list temporarily to NULL and drops the lock to the connection for changing the timeout . However if another thread acquires the lock and happens to get to this function again, it fails out of the function because connection->timeouts is null. This is proprogated down the stack and eventually turns up as an "Out of Memory" abort in the glib bindings. So I have two questions.
<br><br>First does anyone know the designed purpose of this function and what would be a safe way to modify the function so that this case doesn't happen? I can imply some meaning to the function, but hesitate to quickly change some locking scheme I am not completely familiar with.
<br>Secondly is there a good way we can modify the error return system to give better output of what actually happened? We can't change api, but maybe FALSE can represent error, and whoever set FALSE can call a dbus_set_current_error_string(char *), and outside program can print out from dbus_get_current_error_string(char *)?
<br><br>Keith Preston<br><br></pre>