summaryrefslogtreecommitdiff
path: root/callouts
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2014-03-31 09:04:46 -0400
committerDan Winship <danw@gnome.org>2014-04-18 11:32:09 -0400
commit731ca771f840d34dae1bbef7289d9a9eb51563bc (patch)
treed8e10ba0128c8d5c86af9b389cbb46be2f0553f7 /callouts
parentd9334503d77167463edef8cf98445c3678271c5a (diff)
dispatcher: only dispatch one request at a time (rh #1061212)
The dispatcher only runs one script at a time for any given request, but would dispatch multiple requests in parallel. So if a device was brought up and then back down quickly, it could end up dispatching the "down" scripts while the "up" scripts were still running. Or if two devices came up at the same time, two instances of the same "up" script might run at the same time, which could cause problems if they both tried to modify the same file. Fix this by only dispatching the scripts for a single request at a time.
Diffstat (limited to 'callouts')
-rw-r--r--callouts/nm-dispatcher-action.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/callouts/nm-dispatcher-action.c b/callouts/nm-dispatcher-action.c
index 11aa5dc4f1..1a8c99fc00 100644
--- a/callouts/nm-dispatcher-action.c
+++ b/callouts/nm-dispatcher-action.c
@@ -46,10 +46,14 @@
static GMainLoop *loop = NULL;
static gboolean debug = FALSE;
+typedef struct Request Request;
+
typedef struct {
GObject parent;
/* Private data */
+ Request *current_request;
+ GQueue *pending_requests;
guint quit_id;
gboolean persist;
} Handler;
@@ -94,8 +98,6 @@ handler_class_init (HandlerClass *h_class)
{
}
-typedef struct Request Request;
-
static void dispatch_one_script (Request *request);
typedef struct {
@@ -165,10 +167,32 @@ quit_timeout_reschedule (Handler *h)
h->quit_id = g_timeout_add_seconds (10, quit_timeout_cb, NULL);
}
+static void
+start_request (Request *request)
+{
+ request->handler->current_request = request;
+ dispatch_one_script (request);
+}
+
+static void
+next_request (Handler *h)
+{
+ Request *request = g_queue_pop_head (h->pending_requests);
+
+ if (request) {
+ start_request (request);
+ return;
+ }
+
+ h->current_request = NULL;
+ quit_timeout_reschedule (h);
+}
+
static gboolean
next_script (gpointer user_data)
{
Request *request = user_data;
+ Handler *h = request->handler;
GPtrArray *results;
GValueArray *item;
guint i;
@@ -210,10 +234,9 @@ next_script (gpointer user_data)
dbus_g_method_return (request->context, results);
g_ptr_array_unref (results);
-
- quit_timeout_reschedule (request->handler);
request_free (request);
+ next_request (h);
return FALSE;
}
@@ -482,8 +505,10 @@ impl_dispatch (Handler *h,
}
g_slist_free (sorted_scripts);
- /* start dispatching scripts */
- dispatch_one_script (request);
+ if (h->current_request)
+ g_queue_push_tail (h->pending_requests, request);
+ else
+ start_request (request);
}
static void
@@ -661,6 +686,7 @@ main (int argc, char **argv)
if (!handler)
return 1;
handler->persist = persist;
+ handler->pending_requests = g_queue_new ();
dbus_g_object_type_install_info (HANDLER_TYPE, &dbus_glib_nm_dispatcher_object_info);
dbus_g_connection_register_g_object (bus,
@@ -672,7 +698,9 @@ main (int argc, char **argv)
g_main_loop_run (loop);
+ g_queue_free (handler->pending_requests);
g_object_unref (handler);
+
dbus_g_connection_unref (bus);
if (!debug)