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