[PATCH 1/1] fix dhclient probe remove race condition

Martin Xu martin.xu at intel.com
Fri Jul 10 21:37:04 PDT 2009


---
 plugins/dhclient.c |   69 +++++++++++++++++++++++++++++++++-------------------
 1 files changed, 44 insertions(+), 25 deletions(-)

diff --git a/plugins/dhclient.c b/plugins/dhclient.c
index 10f32ff..35242c6 100644
--- a/plugins/dhclient.c
+++ b/plugins/dhclient.c
@@ -43,6 +43,8 @@ struct dhclient_task {
 	GPid pid;
 	int ifindex;
 	gchar *ifname;
+	gboolean dying;
+	struct dhclient_task *pending;
 	struct connman_element *element;
 };
 
@@ -80,8 +82,10 @@ static void kill_task(struct dhclient_task *task)
 {
 	DBG("task %p name %s pid %d", task, task->ifname, task->pid);
 
-	if (task->pid > 0)
+	if (task->pid > 0) {
 		kill(task->pid, SIGTERM);
+		task->dying = TRUE;
+	}
 }
 
 static void unlink_task(struct dhclient_task *task)
@@ -101,6 +105,8 @@ static void unlink_task(struct dhclient_task *task)
 	g_free(pathname);
 }
 
+static int start_dhclient(struct dhclient_task *task);
+
 static void task_died(GPid pid, gint status, gpointer data)
 {
 	struct dhclient_task *task = data;
@@ -117,6 +123,9 @@ static void task_died(GPid pid, gint status, gpointer data)
 
 	unlink_task(task);
 
+	if (task->pending != NULL)
+		start_dhclient(task->pending);
+
 	g_free(task->ifname);
 	g_free(task);
 }
@@ -128,32 +137,11 @@ static void task_setup(gpointer data)
 	DBG("task %p name %s", task, task->ifname);
 }
 
-static int dhclient_probe(struct connman_element *element)
+static int start_dhclient(struct dhclient_task *task)
 {
-	struct dhclient_task *task;
 	char *argv[16], *envp[1], address[128], pidfile[PATH_MAX];
 	char leases[PATH_MAX], config[PATH_MAX], script[PATH_MAX];
 
-	DBG("element %p name %s", element, element->name);
-
-	if (access(DHCLIENT, X_OK) < 0)
-		return -errno;
-
-	task = g_try_new0(struct dhclient_task, 1);
-	if (task == NULL)
-		return -ENOMEM;
-
-	task->ifindex = element->index;
-	task->ifname = connman_inet_ifname(element->index);
-	task->element = element;
-
-	if (task->ifname == NULL) {
-		g_free(task);
-		return -ENOMEM;
-	}
-
-	DBG("request %s", task->ifname);
-
 	snprintf(address, sizeof(address) - 1, "BUSNAME=%s", busname);
 	snprintf(pidfile, sizeof(pidfile) - 1,
 			"%s/dhclient.%s.pid", STATEDIR, task->ifname);
@@ -196,6 +184,39 @@ static int dhclient_probe(struct connman_element *element)
 	return 0;
 }
 
+static int dhclient_probe(struct connman_element *element)
+{
+	struct dhclient_task *task, *pre_task;
+	DBG("element %p name %s", element, element->name);
+
+	if (access(DHCLIENT, X_OK) < 0)
+		return -errno;
+
+	task = g_try_new0(struct dhclient_task, 1);
+	if (task == NULL)
+		return -ENOMEM;
+
+	task->ifindex = element->index;
+	task->ifname = connman_inet_ifname(element->index);
+	task->element = element;
+
+	task->dying = FALSE;
+	task->pending = NULL;
+
+	if (task->ifname == NULL) {
+		g_free(task);
+		return -ENOMEM;
+	}
+
+	pre_task = find_task_by_index(element->index);
+	if (pre_task != NULL && pre_task->dying == TRUE) {
+		pre_task->pending = task;
+		return 0;
+	}
+
+	return start_dhclient(task);
+}
+
 static void dhclient_remove(struct connman_element *element)
 {
 	struct dhclient_task *task;
@@ -203,8 +224,6 @@ static void dhclient_remove(struct connman_element *element)
 	DBG("element %p name %s", element, element->name);
 
 	task = find_task_by_index(element->index);
-	if (task != NULL)
-		task_list = g_slist_remove(task_list, task);
 
 	if (task == NULL)
 		return;
-- 
1.6.1.3



More information about the connman mailing list