diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2009-07-11 14:07:04 -0700 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-07-11 14:07:04 -0700 |
commit | 5da7152b4c25b03088eadebb676ed16ab107c7fd (patch) | |
tree | 4e1f686f2736914a10471e611f3c5c8ea01ee4b9 /plugins | |
parent | 31ca831339412615bb2ba88b0cc706b960f9410f (diff) | |
download | connman-5da7152b4c25b03088eadebb676ed16ab107c7fd.tar.gz connman-5da7152b4c25b03088eadebb676ed16ab107c7fd.tar.bz2 connman-5da7152b4c25b03088eadebb676ed16ab107c7fd.zip |
Fix dhclient probe/remove race condition
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/dhclient.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/plugins/dhclient.c b/plugins/dhclient.c index 90f8e2f5..56e1575d 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; |