summaryrefslogtreecommitdiff
path: root/plugins/dhclient.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-07-11 14:07:04 -0700
committerMarcel Holtmann <marcel@holtmann.org>2009-07-11 14:07:04 -0700
commit5da7152b4c25b03088eadebb676ed16ab107c7fd (patch)
tree4e1f686f2736914a10471e611f3c5c8ea01ee4b9 /plugins/dhclient.c
parent31ca831339412615bb2ba88b0cc706b960f9410f (diff)
downloadconnman-5da7152b4c25b03088eadebb676ed16ab107c7fd.tar.gz
connman-5da7152b4c25b03088eadebb676ed16ab107c7fd.tar.bz2
connman-5da7152b4c25b03088eadebb676ed16ab107c7fd.zip
Fix dhclient probe/remove race condition
Diffstat (limited to 'plugins/dhclient.c')
-rw-r--r--plugins/dhclient.c60
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;