aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Ludviksen <andreas.e.ludviksen@stericsson.com>2011-06-08 15:10:29 +0200
committerSverre Vegge <sverre.vegge@stericsson.com>2011-08-02 22:50:05 +0200
commite0c25b0041b692d4060a165f20dbeafc8d7cf010 (patch)
tree2e0d053f28b841417d5a2ad9c80bc601358cb977
parent0cc5f0c2cf103e9de87d6a55a15c9cefc63f8032 (diff)
downloadu300-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.c132
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);