It could happen that cleaning up the pending message in
agent_receive_message() would as a side effect clear the last
reference to the service via driver context unref function pointer.
Service cleanup would then call connman_agent_cancel(), which would
try to clean up the pending message for the second time as the pending
pointer was still non-NULL.

Fixed by decoupling the pointer to the pending request from the agent
structure before calling agent_request_free().
---
 src/agent.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/src/agent.c b/src/agent.c
index b9b8dd9..37cf524 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -112,6 +112,17 @@ static void agent_request_free(struct 
connman_agent_request *request)
        g_free(request);
 }
 
+static void agent_finalize_pending(struct connman_agent *agent,
+                               DBusMessage *reply)
+{
+       struct connman_agent_request *pending = agent->pending;
+       if (pending) {
+               agent->pending = NULL;
+               pending->callback(reply, pending->user_data);
+               agent_request_free(pending);
+       }
+}
+
 static void agent_receive_message(DBusPendingCall *call, void *user_data);
 
 static int agent_send_next_request(struct connman_agent *agent)
@@ -146,9 +157,7 @@ static int agent_send_next_request(struct connman_agent 
*agent)
        return 0;
 
 fail:
-       agent->pending->callback(NULL, agent->pending->user_data);
-       agent_request_free(agent->pending);
-       agent->pending = NULL;
+       agent_finalize_pending(agent, NULL);
        return -ESRCH;
 }
 
@@ -191,12 +200,9 @@ static void agent_receive_message(DBusPendingCall *call, 
void *user_data)
                send_cancel_request(agent, agent->pending);
        }
 
-       agent->pending->callback(reply, agent->pending->user_data);
+       agent_finalize_pending(agent, reply);
        dbus_message_unref(reply);
 
-       agent_request_free(agent->pending);
-       agent->pending = NULL;
-
        err = agent_send_next_request(agent);
        if (err < 0 && err != -EBUSY)
                DBG("send next request failed (%s/%d)", strerror(-err), -err);
@@ -456,9 +462,7 @@ static void cancel_all_requests(struct connman_agent *agent)
                if (agent->pending->call)
                        send_cancel_request(agent, agent->pending);
 
-               agent->pending->callback(NULL, agent->pending->user_data);
-               agent_request_free(agent->pending);
-               agent->pending = NULL;
+               agent_finalize_pending(agent, NULL);
        }
 
        for (list = agent->queue; list; list = list->next) {
@@ -521,12 +525,7 @@ void connman_agent_cancel(void *user_context)
                        if (agent->pending->call)
                                send_cancel_request(agent, agent->pending);
 
-                       agent->pending->callback(NULL,
-                                               agent->pending->user_data);
-
-                       agent_request_free(agent->pending);
-
-                       agent->pending = NULL;
+                       agent_finalize_pending(agent, NULL);
 
                        err = agent_send_next_request(agent);
                        if (err < 0 && err != -EBUSY)
-- 
1.8.5.3

_______________________________________________
connman mailing list
connman@connman.net
https://lists.connman.net/mailman/listinfo/connman

Reply via email to