Bug 768306 - Patch 1: Fix error handling in unpacking DBus replies, set up DBus blocking call handling thread; r=mrbkap

This commit is contained in:
Kyle Machulis 2012-08-08 10:46:39 -07:00
parent 894868aa63
commit 11d7f94bbe
6 changed files with 94 additions and 53 deletions

View File

@ -22,34 +22,37 @@ using namespace mozilla;
USING_BLUETOOTH_NAMESPACE
nsRefPtr<BluetoothService> gBluetoothService;
nsCOMPtr<nsIThread> gToggleBtThread;
int gPendingInitCount = 0;
bool gInShutdown = false;
static nsRefPtr<BluetoothService> gBluetoothService;
static bool gInShutdown = false;
NS_IMPL_ISUPPORTS1(BluetoothService, nsIObserver)
class ToggleBtAck : public nsRunnable
{
public:
ToggleBtAck(bool aEnabled) :
mEnabled(aEnabled)
{
}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
gPendingInitCount--;
if (gPendingInitCount) {
return NS_OK;
if (!mEnabled || gInShutdown) {
nsCOMPtr<nsIThread> t;
gBluetoothService->mBluetoothCommandThread.swap(t);
t->Shutdown();
}
if (gInShutdown) {
gBluetoothService = nullptr;
}
nsCOMPtr<nsIThread> t;
gToggleBtThread.swap(t);
t->Shutdown();
return NS_OK;
}
bool mEnabled;
};
class ToggleBtTask : public nsRunnable
@ -82,7 +85,7 @@ public:
// Always has to be called since this is where we take care of our reference
// count for runnables. If there's an error, replyError won't be empty, so
// consider our status flipped.
nsCOMPtr<nsIRunnable> ackTask = new ToggleBtAck();
nsCOMPtr<nsIRunnable> ackTask = new ToggleBtAck(mEnabled);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
NS_WARNING("Failed to dispatch to main thread!");
}
@ -168,17 +171,16 @@ BluetoothService::StartStopBluetooth(BluetoothReplyRunnable* aResultRunnable,
NS_ERROR("Start called while in shutdown!");
return NS_ERROR_FAILURE;
}
if (!gToggleBtThread) {
nsresult rv = NS_NewNamedThread("BluetoothCtrl",
getter_AddRefs(gToggleBtThread));
if (!mBluetoothCommandThread) {
nsresult rv = NS_NewNamedThread("BluetoothCmd",
getter_AddRefs(mBluetoothCommandThread));
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aStart, aResultRunnable);
if (NS_FAILED(gToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL))) {
if (NS_FAILED(mBluetoothCommandThread->Dispatch(r, NS_DISPATCH_NORMAL))) {
NS_WARNING("Cannot dispatch firmware loading task!");
return NS_ERROR_FAILURE;
}
gPendingInitCount++;
return NS_OK;
}

View File

@ -192,6 +192,19 @@ public:
const nsAString& aPattern,
int aAttributeId) = 0;
/**
* Due to the fact that some operations require multiple calls, a
* CommandThread is created that can run blocking, platform-specific calls
* where either no asynchronous equivilent exists, or else where multiple
* asynchronous calls would require excessive runnable bouncing between main
* thread and IO thread.
*
* For instance, when we retrieve an Adapter object, we would like it to come
* with all of its properties filled in and registered as an agent, which
* requires a minimum of 3 calls to platform specific code on some platforms.
*
*/
nsCOMPtr<nsIThread> mBluetoothCommandThread;
protected:
BluetoothService()
{

View File

@ -149,8 +149,14 @@ public:
};
bool
IsDBusMessageError(DBusMessage* aMsg, nsAString& aError)
IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
{
if(aErr && dbus_error_is_set(aErr)) {
aErrorStr = NS_ConvertUTF8toUTF16(aErr->message);
LOG_AND_FREE_DBUS_ERROR(aErr);
return true;
}
DBusError err;
dbus_error_init(&err);
if (dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_ERROR) {
@ -159,12 +165,15 @@ IsDBusMessageError(DBusMessage* aMsg, nsAString& aError)
&error_msg, DBUS_TYPE_INVALID) ||
!error_msg) {
if (dbus_error_is_set(&err)) {
aError = NS_ConvertUTF8toUTF16(err.message);
aErrorStr = NS_ConvertUTF8toUTF16(err.message);
LOG_AND_FREE_DBUS_ERROR(&err);
return true;
} else {
aErrorStr.AssignLiteral("Unknown Error");
return true;
}
} else {
aError = NS_ConvertUTF8toUTF16(error_msg);
aErrorStr = NS_ConvertUTF8toUTF16(error_msg);
return true;
}
}
@ -173,15 +182,14 @@ IsDBusMessageError(DBusMessage* aMsg, nsAString& aError)
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue, const nsAString& aError)
const BluetoothValue& aValue, const nsAString& aErrorStr)
{
// Reply will be deleted by the runnable after running on main thread
BluetoothReply* reply;
if (!aError.IsEmpty()) {
nsString err(aError);
if (!aErrorStr.IsEmpty()) {
nsString err(aErrorStr);
reply = new BluetoothReply(BluetoothReplyError(err));
}
else {
} else {
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
}
@ -192,12 +200,12 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
}
void
UnpackObjectPathMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr,
BluetoothValue& aValue, nsAString& aErrorStr)
{
DBusError err;
dbus_error_init(&err);
if (!IsDBusMessageError(aMsg, aErrorStr)) {
if (!IsDBusMessageError(aMsg, aErr, aErrorStr)) {
NS_ASSERTION(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
"Got dbus callback that's not a METHOD_RETURN!");
const char* object_path;
@ -214,7 +222,7 @@ UnpackObjectPathMessage(DBusMessage* aMsg, BluetoothValue& aValue,
}
}
typedef void (*UnpackFunc)(DBusMessage*, BluetoothValue&, nsAString&);
typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
void
RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
@ -228,23 +236,24 @@ RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
nsString replyError;
BluetoothValue v;
aFunc(aMsg, v, replyError);
aFunc(aMsg, nsnull, v, replyError);
DispatchBluetoothReply(replyRunnable, v, replyError);
}
void
GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackObjectPathMessage);
RunDBusCallback(aMsg, aBluetoothReplyRunnable,
UnpackObjectPathMessage);
}
void
UnpackVoidMessage(DBusMessage* aMsg, BluetoothValue& aValue,
UnpackVoidMessage(DBusMessage* aMsg, DBusError* aErr, BluetoothValue& aValue,
nsAString& aErrorStr)
{
DBusError err;
dbus_error_init(&err);
if (!IsDBusMessageError(aMsg, aErrorStr) &&
if (!IsDBusMessageError(aMsg, aErr, aErrorStr) &&
dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN &&
!dbus_message_get_args(aMsg, &err, DBUS_TYPE_INVALID)) {
if (dbus_error_is_set(&err)) {
@ -257,7 +266,8 @@ UnpackVoidMessage(DBusMessage* aMsg, BluetoothValue& aValue,
void
GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackVoidMessage);
RunDBusCallback(aMsg, aBluetoothReplyRunnable,
UnpackVoidMessage);
}
bool
@ -381,11 +391,13 @@ ParseProperties(DBusMessageIter* aIter,
aValue = props;
}
void UnpackPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr, Properties* aPropertyTypes,
const int aPropertyTypeLen)
void
UnpackPropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
BluetoothValue& aValue, nsAString& aErrorStr,
Properties* aPropertyTypes,
const int aPropertyTypeLen)
{
if (!IsDBusMessageError(aMsg, aErrorStr) &&
if (!IsDBusMessageError(aMsg, aErr, aErrorStr) &&
dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
DBusMessageIter iter;
if (!dbus_message_iter_init(aMsg, &iter)) {
@ -397,26 +409,32 @@ void UnpackPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
}
}
void UnpackAdapterPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
void
UnpackAdapterPropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
UnpackPropertiesMessage(aMsg, aErr, aValue, aErrorStr,
sAdapterProperties,
ArrayLength(sAdapterProperties));
}
void UnpackDevicePropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
void
UnpackDevicePropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
UnpackPropertiesMessage(aMsg, aErr, aValue, aErrorStr,
sDeviceProperties,
ArrayLength(sDeviceProperties));
}
void UnpackManagerPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
void
UnpackManagerPropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
UnpackPropertiesMessage(aMsg, aErr, aValue, aErrorStr,
sManagerProperties,
ArrayLength(sManagerProperties));
}
@ -424,19 +442,22 @@ void UnpackManagerPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
void
GetManagerPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackManagerPropertiesMessage);
RunDBusCallback(aMsg, aBluetoothReplyRunnable,
UnpackManagerPropertiesMessage);
}
void
GetAdapterPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackAdapterPropertiesMessage);
RunDBusCallback(aMsg, aBluetoothReplyRunnable,
UnpackAdapterPropertiesMessage);
}
void
GetDevicePropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackDevicePropertiesMessage);
RunDBusCallback(aMsg, aBluetoothReplyRunnable,
UnpackDevicePropertiesMessage);
}
static DBusCallback sBluetoothDBusPropCallbacks[] =
@ -611,7 +632,6 @@ BluetoothDBusService::StartInternal()
}
if (NS_FAILED(EstablishDBusConnection())) {
NS_WARNING("Cannot start DBus connection!");
StopDBus();
return NS_ERROR_FAILURE;
}

View File

@ -199,7 +199,7 @@ DBusMessage * dbus_func_args_timeout_valist(DBusConnection *conn,
/* Make the call. */
reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout_ms, err);
if (!return_error && dbus_error_is_set(err)) {
//LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg);
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg);
}
done:
@ -212,6 +212,7 @@ done:
DBusMessage * dbus_func_args_timeout(DBusConnection *conn,
int timeout_ms,
DBusError* err,
const char *path,
const char *ifc,
const char *func,
@ -220,7 +221,7 @@ DBusMessage * dbus_func_args_timeout(DBusConnection *conn,
DBusMessage *ret;
va_list lst;
va_start(lst, first_arg_type);
ret = dbus_func_args_timeout_valist(conn, timeout_ms, NULL,
ret = dbus_func_args_timeout_valist(conn, timeout_ms, err,
path, ifc, func,
first_arg_type, lst);
va_end(lst);

View File

@ -90,6 +90,7 @@ DBusMessage* dbus_func_args_error(DBusConnection* conn,
DBusMessage* dbus_func_args_timeout(DBusConnection* conn,
int timeout_ms,
DBusError* err,
const char* path,
const char* ifc,
const char* func,

View File

@ -31,6 +31,10 @@ public:
RawDBusConnection();
~RawDBusConnection();
nsresult EstablishDBusConnection();
DBusConnection* GetConnection() {
return mConnection;
}
protected:
Scoped<ScopedDBusConnectionPtrTraits> mConnection;
};