gisi: remove before notify
authorPekka Pessi <Pekka.Pessi@nokia.com>
Wed, 12 Jan 2011 19:24:09 +0000 (21:24 +0200)
committerAki Niemi <aki.niemi@nokia.com>
Tue, 18 Jan 2011 20:29:24 +0000 (22:29 +0200)
Just in case, remove pending operations before calling notifys.
The notify function can remove client, service or modem.

gisi/client.c
gisi/modem.c

index 03ed5de..85e1fa7 100644 (file)
@@ -66,11 +66,11 @@ static void pending_resp_notify(const GIsiMessage *msg, void *data)
        if (pd == NULL)
                return;
 
-       if (pd->notify != NULL)
-               pd->notify(msg, pd->data);
-
        pd->client->pending = g_slist_remove(pd->client->pending,
                                                g_isi_pending_from_msg(msg));
+
+       if (pd->notify != NULL)
+               pd->notify(msg, pd->data);
 }
 
 static void pending_notify(const GIsiMessage *msg, void *data)
index 0682666..1655929 100644 (file)
@@ -155,9 +155,41 @@ static void pending_dispatch(GIsiPending *pend, GIsiMessage *msg)
                g_isi_msg_resource(msg), g_isi_msg_id(msg),
                g_isi_msg_utid(msg));
 
+       msg->private = pend;
+
        pend->notify(msg, pend->data);
 }
 
+static void pending_remove_and_dispatch(GIsiPending *op, GIsiMessage *msg)
+{
+       GIsiModem *modem;
+
+       op->service->pending = g_slist_remove(op->service->pending, op);
+
+       if (op->notify == NULL || msg == NULL)
+               goto destroy;
+
+       modem = op->service->modem;
+
+       ISIDBG(modem, "%s %s to %p [res=0x%02X, id=0x%02X, utid=0x%02X]",
+               g_isi_msg_strerror(msg), pend_type_to_str(op->type), op,
+               g_isi_msg_resource(msg), g_isi_msg_id(msg),
+               g_isi_msg_utid(msg));
+
+       msg->private = op;
+
+       op->notify(msg, op->data);
+
+destroy:
+       if (op->timeout > 0)
+               g_source_remove(op->timeout);
+
+       if (op->destroy != NULL)
+               op->destroy(op->data);
+
+       g_free(op);
+}
+
 static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg,
                                gboolean is_indication)
 {
@@ -169,7 +201,6 @@ static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg,
        while (l != NULL) {
                GSList *next = l->next;
                GIsiPending *pend = l->data;
-               msg->private = pend;
 
                /*
                 * REQs, NTFs and INDs are dispatched on message ID.  While
@@ -194,22 +225,16 @@ static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg,
                } else if (pend->type == GISI_MESSAGE_TYPE_RESP &&
                                !is_indication && pend->utid == utid) {
 
-                       pending_dispatch(pend, msg);
-                       pend->notify = NULL;
-
-                       g_isi_pending_remove(pend);
+                       pending_remove_and_dispatch(pend, msg);
                        break;
 
                } else if (pend->type == GISI_MESSAGE_TYPE_COMMON &&
                                msgid == COMMON_MESSAGE &&
                                pend->msgid == COMM_ISI_VERSION_GET_REQ) {
 
-                       pending_dispatch(pend, msg);
-                       pend->notify = NULL;
-
-                       g_isi_pending_remove(pend);
-
+                       pending_remove_and_dispatch(pend, msg);
                }
+
                l = next;
        }
 }
@@ -634,16 +659,15 @@ static void vtrace(struct sockaddr_pn *dst,
 
 static gboolean resp_timeout(gpointer data)
 {
-       GIsiPending *resp = data;
+       GIsiPending *op = data;
        GIsiMessage msg = {
                .error = ETIMEDOUT,
-               .private = resp,
        };
 
-       pending_dispatch(resp, &msg);
-       resp->notify = NULL;
+       op->timeout = 0;
+
+       pending_remove_and_dispatch(op, &msg);
 
-       g_isi_pending_remove(resp);
        return FALSE;
 }
 
@@ -755,8 +779,6 @@ void g_isi_pending_remove(GIsiPending *op)
        if (op == NULL)
                return;
 
-       op->service->pending = g_slist_remove(op->service->pending, op);
-
        if (op->type == GISI_MESSAGE_TYPE_IND)
                service_subs_decr(op->service);
 
@@ -766,12 +788,14 @@ void g_isi_pending_remove(GIsiPending *op)
        if (op->type == GISI_MESSAGE_TYPE_RESP && op->notify != NULL) {
                GIsiMessage msg = {
                        .error = ESHUTDOWN,
-                       .private = op,
                };
-               op->notify(&msg, op->data);
-               op->notify = NULL;
+
+               pending_remove_and_dispatch(op, &msg);
+               return;
        }
 
+       op->service->pending = g_slist_remove(op->service->pending, op);
+
        pending_destroy(op, NULL);
 }
 
@@ -1045,14 +1069,11 @@ static gboolean reachable_notify(gpointer data)
        };
        GIsiMessage msg = {
                .version = &mux->version,
-               .private = pong,
                .addr = &addr,
        };
 
-       pending_dispatch(pong, &msg);
-       pong->notify = NULL;
+       pending_remove_and_dispatch(pong, &msg);
 
-       g_isi_pending_remove(pong);
        return FALSE;
 }