Bug 853550: Cleanup DBus thread handling, r=qdot

For replacing the Bluetooth command thread with a LazyIdleThread,
we need to make sure that the DBus service thread is shutdown from
within the main thread.

This patch changes the DBus stop code to cleanup the DBusThread
structure from the service thread to prevent race conditions during
shutdown. The DBus service thread itself gets shutdown from the main
thread to fulfill the requirements of LazyIdleThread. The patch also
makes sure that it's not possible to accidently dispatch a runnable
while the DBus thread terminates.
This commit is contained in:
Thomas Zimmermann 2013-08-30 20:18:40 +02:00
parent 5b04320f03
commit fa9d8dc375

View File

@ -479,11 +479,13 @@ public:
}
}
mConnection->CleanUp();
return NS_OK;
}
private:
DBusThread* mConnection;
nsRefPtr<DBusThread> mConnection;
};
static StaticRefPtr<DBusThread> gDBusThread;
@ -532,30 +534,23 @@ StopDBus()
MOZ_ASSERT(!NS_IsMainThread());
NS_ENSURE_TRUE(gDBusServiceThread, true);
if (gDBusThread) {
nsRefPtr<DBusThread> dbusThread(gDBusThread);
gDBusThread = nullptr;
if (dbusThread) {
static const char data = DBUS_EVENT_LOOP_EXIT;
ssize_t wret = TEMP_FAILURE_RETRY(write(gDBusThread->mControlFdW.get(),
ssize_t wret = TEMP_FAILURE_RETRY(write(dbusThread->mControlFdW.get(),
&data, sizeof(data)));
NS_ENSURE_TRUE(wret == 1, false);
}
#ifdef DEBUG
LOG("DBus Thread Joining\n");
#endif
if (NS_FAILED(gDBusServiceThread->Shutdown())) {
NS_WARNING("DBus thread shutdown failed!");
}
nsRefPtr<nsIThread> dbusServiceThread(gDBusServiceThread);
gDBusServiceThread = nullptr;
#ifdef DEBUG
LOG("DBus Thread Joined\n");
#endif
if (gDBusThread) {
gDBusThread->CleanUp();
gDBusThread = nullptr;
}
nsRefPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(dbusServiceThread, &nsIThread::Shutdown);
nsresult rv = NS_DispatchToMainThread(runnable);
NS_ENSURE_SUCCESS(rv, false);
return true;
}
@ -563,13 +558,16 @@ StopDBus()
nsresult
DispatchToDBusThread(nsIRunnable* event)
{
MOZ_ASSERT(gDBusServiceThread);
MOZ_ASSERT(gDBusThread);
nsRefPtr<nsIThread> dbusServiceThread(gDBusServiceThread);
nsRefPtr<DBusThread> dbusThread(gDBusThread);
nsresult rv = gDBusServiceThread->Dispatch(event, NS_DISPATCH_NORMAL);
NS_ENSURE_TRUE(dbusServiceThread.get() && dbusThread.get(),
NS_ERROR_NOT_INITIALIZED);
nsresult rv = dbusServiceThread->Dispatch(event, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
gDBusThread->WakeUp();
dbusThread->WakeUp();
return NS_OK;
}