diff options
author | Andreas Ludviksen <andreas.e.ludviksen@stericsson.com> | 2011-06-08 15:10:29 +0200 |
---|---|---|
committer | Sverre Vegge <sverre.vegge@stericsson.com> | 2011-08-02 22:50:05 +0200 |
commit | e0c25b0041b692d4060a165f20dbeafc8d7cf010 (patch) | |
tree | 2e0d053f28b841417d5a2ad9c80bc601358cb977 | |
parent | 0cc5f0c2cf103e9de87d6a55a15c9cefc63f8032 (diff) | |
download | u300-e0c25b0041b692d4060a165f20dbeafc8d7cf010.tar.gz |
Manager: Separate query and listen Dbus-connections.
Fix a race-condition where two threads might use the same dbus connection at
the same time.
Flush Dbus messages before statring the Dbus-thread. Initial Dbus messages are
buffered, and not handled until the first trigger to poll(). This will flush
these messages before starting the Dbus thread.
Signed-off-by: Sverre Vegge <sverre.vegge@stericsson.com>
-rw-r--r-- | u300-ril-manager.c | 132 |
1 files changed, 82 insertions, 50 deletions
diff --git a/u300-ril-manager.c b/u300-ril-manager.c index bf4fe43..0a0649d 100644 --- a/u300-ril-manager.c +++ b/u300-ril-manager.c @@ -384,6 +384,44 @@ static void notifyForEvent(int index, short event) { __func__, index); } +static void flushDbusEvents(DBusConnection *dbcon) { + DBusMessageIter args; + DBusMessage *dbmsg; + char *signame = NULL; + int res = 0; + + for (;;) { + res = dbus_connection_get_dispatch_status(dbcon); + switch (res) { + case DBUS_DISPATCH_COMPLETE: + return; + case DBUS_DISPATCH_NEED_MEMORY: + LOGD("%s(): needs more memory. spinning.", __func__); + sleep(1); + break; + case DBUS_DISPATCH_DATA_REMAINS: + dbmsg = dbus_connection_pop_message(dbcon); + if (dbus_message_is_signal(dbmsg, "com.stericsson.mid.Modem", + "StateChange")) { + if (!dbus_message_iter_init(dbmsg, &args)) { + LOGD("%s(): Message has no arguments!", __func__); + } else if (DBUS_TYPE_STRING != + dbus_message_iter_get_arg_type(&args)) { + LOGD("%s(): Argument is not string!", __func__); + } else { + dbus_message_iter_get_basic(&args, &signame); + LOGD("%s(): Flushing Signal with value \"%s\"", + __func__, signame); + } + } + break; + default: + /* This should not happen */ + break; + } + } +} + static void processDbusEvent(DBusConnection *dbcon) { int res = 0; for (;;) { @@ -407,44 +445,6 @@ static void processDbusEvent(DBusConnection *dbcon) { } } -static int sendMsgToMidWithoutReply(DBusConnection *dbcon, char *msg) -{ - DBusError err; - DBusMessage *dbmsg; - int res = 0; - - /* Initialize the dbus error return value */ - dbus_error_init(&err); - - dbmsg = dbus_message_new_method_call(DBUS_CONNECTION_NAME, - DBUS_OBJECT_PATH, - DBUS_OBJECT_INTERFACE, - msg); - if (dbmsg == NULL) { - LOGE("%s(): cannot create message", __func__); - res = -1; - goto finally1; - } - - dbus_message_set_no_reply(dbmsg, TRUE); - - if (!dbus_connection_send(dbcon, dbmsg, NULL)) { - LOGE("IPC message send error"); - res = -1; - goto finally2; - }; - - dbus_connection_flush(dbcon); - -finally2: - /* Drop reference count on the message */ - dbus_message_unref(dbmsg); -finally1: - dbus_error_free(&err); - - return res; -} - static int requestMIDWithResponse(DBusConnection *dbcon, char *requestMethod, char *response) @@ -565,10 +565,12 @@ static void *managerRunner(void *param) #ifndef EXTERNAL_MODEM_CONTROL_MODULE_DISABLED /***************************************************** + * Dbus-connection for listening: * Loop until we have connection to Dbus daemon * *****************************************************/ DBusError dbusErr; - DBusConnection *dbcon = NULL; + DBusConnection *listenDbcon = NULL; + DBusConnection *queryDbcon = NULL; bool dbusIsHere = false; /* Initial shutdown flag when Dbus enabled*/ @@ -577,18 +579,19 @@ static void *managerRunner(void *param) /* Connect to system dbus */ do { dbus_error_init(&dbusErr); - dbcon = dbus_bus_get(DBUS_BUS_SYSTEM, &dbusErr); + listenDbcon = dbus_bus_get(DBUS_BUS_SYSTEM, &dbusErr); - if (!dbcon || dbus_error_is_set(&dbusErr)) { - LOGI("[DBUS]: connect to DBUS daemon returned error (%s).Will try" - " again in %d second(s)", dbusErr.name, DBUS_CONNECT_DELAY); + if (!listenDbcon || dbus_error_is_set(&dbusErr)) { + LOGI("[DBUS]: connect to DBUS(listenDbcon) daemon returned error (%s)." + "Will try again in %d second(s)", + dbusErr.name, DBUS_CONNECT_DELAY); dbus_error_free(&dbusErr); sleep(DBUS_CONNECT_DELAY); } else dbusIsHere = true; } while (!dbusIsHere); - LOGI("[DBUS]: Connected to system dbus."); + LOGI("[DBUS]: listenDbcon Connected to system dbus."); ret = pthread_attr_init(&attr); if (ret != 0) LOGW("%s(): Failed to initialize dbus pthread attribute: %s", @@ -600,9 +603,10 @@ static void *managerRunner(void *param) "attribute: %s", __func__, strerror(ret)); /************************************************* + * Dbus-connection for listening: * Configure Dbus Connection. * *************************************************/ - if (!dbus_connection_set_watch_functions(dbcon, addWatch, + if (!dbus_connection_set_watch_functions(listenDbcon, addWatch, removeWatch, NULL, NULL, NULL)) { LOGE("%s(): dbus_connection_set_watch_functions failed.", __func__); } @@ -613,7 +617,7 @@ static void *managerRunner(void *param) * Listen only signal from com.stericsson.mid.Modem interface (MID * state changes) */ - dbus_bus_add_match(dbcon, + dbus_bus_add_match(listenDbcon, "type='signal', interface='com.stericsson.mid.Modem'", &dbusErr); if (dbus_error_is_set(&dbusErr)) { LOGE("%s(): DBUS match error %s: %s.", __func__, @@ -622,21 +626,49 @@ static void *managerRunner(void *param) } /* Add a message filter to process incoming messages */ - if (!dbus_connection_add_filter(dbcon, + if (!dbus_connection_add_filter(listenDbcon, (DBusHandleMessageFunction)midSignalHandler, NULL, NULL)) { LOGE("%s(): DBUS filter error.", __func__); } + /***************************************************** + * Dbus-connection for query: + * Loop until we have connection to Dbus daemon * + *****************************************************/ + dbusIsHere = false; + /* Connect to system dbus */ + do { + dbus_error_init(&dbusErr); + queryDbcon = dbus_bus_get(DBUS_BUS_SYSTEM, &dbusErr); + + if (!queryDbcon || dbus_error_is_set(&dbusErr)) { + LOGI("[DBUS]: connect to DBUS(queryDbcon) daemon returned error (%s)." + "Will try again in %d second(s)", + dbusErr.name, DBUS_CONNECT_DELAY); + dbus_error_free(&dbusErr); + sleep(DBUS_CONNECT_DELAY); + } else + dbusIsHere = true; + } while (!dbusIsHere); + + LOGI("[DBUS]: queryDbcon Connected to system dbus."); + /********************************************************** * Need to be sure CAIF interfaces are up. Wait for * * "on" message, and release command threads immediately. * * ToDo: Add mutex, and wait for 'on' instead. * **********************************************************/ - while (!queryModemOn(dbcon)) + while (!queryModemOn(queryDbcon)) sleep(DBUS_CONNECT_DELAY); + /** + * Need to empty the listen-buffer initially. + * This must be done before we release command threads. + */ + flushDbusEvents(listenDbcon); + ret = pthread_create(&s_tid_dbusRunner, &attr, - dbusAndThreadRunner, (void *)dbcon); + dbusAndThreadRunner, (void *)listenDbcon); if (ret != 0) { LOGE("%s(): Failed to create dbus runner thread: %s. Asserting." , __func__, strerror(ret)); @@ -742,7 +774,7 @@ static void *managerRunner(void *param) if (g_managerRelease) { /* Signal MID to restart Modem */ - if (requestMIDWithResponse(dbcon, "Reboot", pResponse) == 0) { + if (requestMIDWithResponse(queryDbcon, "Reboot", pResponse) == 0) { if (strncmp(pResponse, "OK", 2) == 0) { LOGI("%s(): MID \"reboot\" request returned %s. " "Modem restarting!", __func__, pResponse); |