From 5da7152b4c25b03088eadebb676ed16ab107c7fd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 11 Jul 2009 14:07:04 -0700 Subject: [PATCH] Fix dhclient probe/remove race condition --- plugins/dhclient.c | 60 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/plugins/dhclient.c b/plugins/dhclient.c index 90f8e2f..56e1575 100644 --- a/plugins/dhclient.c +++ b/plugins/dhclient.c @@ -45,6 +45,7 @@ struct dhclient_task { int ifindex; gchar *ifname; struct connman_element *element; + struct dhclient_task *pending; }; static GSList *task_list = NULL; @@ -107,6 +108,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; @@ -123,6 +126,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); } @@ -136,32 +142,11 @@ static void task_setup(gpointer data) task->killed = FALSE; } -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); @@ -204,6 +189,37 @@ static int dhclient_probe(struct connman_element *element) return 0; } +static int dhclient_probe(struct connman_element *element) +{ + struct dhclient_task *task, *previous; + 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; + } + + previous= find_task_by_index(element->index); + if (previous != NULL) { + previous->pending = task; + kill_task(previous); + return 0; + } + + return start_dhclient(task); +} + static void dhclient_remove(struct connman_element *element) { struct dhclient_task *task; -- 2.7.4