Merge lp:~a-j-buxton/libindicator/remove-timeout into lp:libindicator/14.04

Proposed by Alistair Buxton
Status: Needs review
Proposed branch: lp:~a-j-buxton/libindicator/remove-timeout
Merge into: lp:libindicator/14.04
Diff against target: 175 lines (+4/-81)
1 file modified
libindicator/indicator-service.c (+4/-81)
To merge this branch: bzr merge lp:~a-j-buxton/libindicator/remove-timeout
Reviewer Review Type Date Requested Status
Ted Gould Pending
Review via email: mp+198070@code.launchpad.net

Description of the change

This removes the timeout shutdown code from indicator-service.

This code was intended to allow the services to shut down automatically when using dbus activation and nothing was using the service any more. Indicators are now started by upstart or xdg-autostart, and this code becomes a problem. If the indicator is started by upstart and it exits, upstart will just keep running it again and again until it kills the job "respawning too fast". If the service was started by xdg-autostart and it decides to exit, nothing will start it again. This leads to indicators mysteriously disappearing from the panel, or never loading up in the first place due to race conditions.

If you haven't, please also see:

https://code.launchpad.net/~ted/libindicator/upstart-no-dbus/+merge/166269

This is another MR on libindicator dealing with the upstart changes, but as far as I can tell it does not deal with this specific issue.

To post a comment you must log in.

Unmerged revisions

519. By Alistair Buxton

Remove the shutdown timeout.

Since indicators are now started by upstart, and not on demand, this
code is not needed.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libindicator/indicator-service.c'
--- libindicator/indicator-service.c 2013-10-24 02:08:35 +0000
+++ libindicator/indicator-service.c 2013-12-06 14:39:26 +0000
@@ -42,7 +42,6 @@
42/**42/**
43 IndicatorSevicePrivate:43 IndicatorSevicePrivate:
44 @name: The DBus well known name for the service.44 @name: The DBus well known name for the service.
45 @timeout: The source ID for the timeout event.
46 @watcher: A list of processes on dbus that are watching us.45 @watcher: A list of processes on dbus that are watching us.
47 @this_service_version: The version to hand out that we're46 @this_service_version: The version to hand out that we're
48 implementing. May not be set, so we'll send zero (default).47 implementing. May not be set, so we'll send zero (default).
@@ -54,8 +53,6 @@
54 gchar * name;53 gchar * name;
55 GDBusConnection * bus;54 GDBusConnection * bus;
56 GCancellable * bus_cancel;55 GCancellable * bus_cancel;
57 guint timeout;
58 guint timeout_length;
59 GHashTable * watchers;56 GHashTable * watchers;
60 guint this_service_version;57 guint this_service_version;
61 guint dbus_registration;58 guint dbus_registration;
@@ -188,24 +185,13 @@
188185
189 /* Get the private variables in a decent state */186 /* Get the private variables in a decent state */
190 priv->name = NULL;187 priv->name = NULL;
191 priv->timeout = 0;
192 priv->watchers = NULL;188 priv->watchers = NULL;
193 priv->bus = NULL;189 priv->bus = NULL;
194 priv->bus_cancel = NULL;190 priv->bus_cancel = NULL;
195 priv->this_service_version = 0;191 priv->this_service_version = 0;
196 priv->timeout_length = 500;
197 priv->dbus_registration = 0;192 priv->dbus_registration = 0;
198 priv->replace_mode = FALSE;193 priv->replace_mode = FALSE;
199194
200 const gchar * timeoutenv = g_getenv("INDICATOR_SERVICE_SHUTDOWN_TIMEOUT");
201 if (timeoutenv != NULL) {
202 gdouble newtimeout = g_strtod(timeoutenv, NULL);
203 if (newtimeout >= 1.0f) {
204 priv->timeout_length = newtimeout;
205 g_debug("Setting shutdown timeout to: %u", priv->timeout_length);
206 }
207 }
208
209 const gchar * replaceenv = g_getenv("INDICATOR_SERVICE_REPLACE_MODE");195 const gchar * replaceenv = g_getenv("INDICATOR_SERVICE_REPLACE_MODE");
210 if (replaceenv != NULL) {196 if (replaceenv != NULL) {
211 priv->replace_mode = TRUE;197 priv->replace_mode = TRUE;
@@ -226,8 +212,7 @@
226 return;212 return;
227}213}
228214
229/* Unrefcounting the proxies and making sure that our215/* Unrefcounting the proxies. */
230 timeout doesn't come to haunt us. */
231static void216static void
232indicator_service_dispose (GObject *object)217indicator_service_dispose (GObject *object)
233{218{
@@ -235,11 +220,6 @@
235220
236 g_clear_pointer (&priv->watchers, g_hash_table_destroy);221 g_clear_pointer (&priv->watchers, g_hash_table_destroy);
237222
238 if (priv->timeout != 0) {
239 g_source_remove(priv->timeout);
240 priv->timeout = 0;
241 }
242
243 if (priv->dbus_registration != 0) {223 if (priv->dbus_registration != 0) {
244 g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration);224 g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration);
245 /* Don't care if it fails, there's nothing we can do */225 /* Don't care if it fails, there's nothing we can do */
@@ -415,43 +395,14 @@
415 return;395 return;
416}396}
417397
418/* This is the function that gets executed if we timeout
419 because there are no watchers. We sent the shutdown
420 signal and hope someone does something sane with it. */
421static gboolean
422timeout_no_watchers (gpointer data)
423{
424 g_warning("No watchers, service timing out.");
425 if (g_getenv("INDICATOR_ALLOW_NO_WATCHERS") == NULL) {
426 g_signal_emit(G_OBJECT(data), signals[SHUTDOWN], 0, TRUE);
427 } else {
428 g_warning("\tblocked by environment variable.");
429 }
430 return FALSE;
431}
432
433/* Callback saying that the name we were looking for has been398/* Callback saying that the name we were looking for has been
434 found and we've got it. Now start the timer to see if anyone399 found and we've got it. */
435 cares about us. */
436static void400static void
437try_and_get_name_acquired_cb (GDBusConnection * connection, const gchar * name, gpointer user_data)401try_and_get_name_acquired_cb (GDBusConnection * connection, const gchar * name, gpointer user_data)
438{402{
439 g_return_if_fail(connection != NULL);403 g_return_if_fail(connection != NULL);
440 g_return_if_fail(INDICATOR_IS_SERVICE(user_data));404 g_return_if_fail(INDICATOR_IS_SERVICE(user_data));
441405
442 IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(user_data);
443
444 /* Check to see if we already had a timer, if so we want to
445 extend it a bit. */
446 if (priv->timeout != 0) {
447 g_source_remove(priv->timeout);
448 priv->timeout = 0;
449 }
450
451 /* Allow some extra time at start up as things can be in high
452 contention then. */
453 priv->timeout = g_timeout_add(priv->timeout_length * 2, timeout_no_watchers, user_data);
454
455 return;406 return;
456}407}
457408
@@ -480,15 +431,6 @@
480431
481 g_dbus_connection_send_message(connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);432 g_dbus_connection_send_message(connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
482 g_object_unref(message);433 g_object_unref(message);
483
484 /* Check to see if we need to clean up a timeout */
485 if (priv->timeout != 0) {
486 g_source_remove(priv->timeout);
487 priv->timeout = 0;
488 }
489
490 /* Set a timeout for no watchers if we can't get the name */
491 priv->timeout = g_timeout_add(priv->timeout_length * 4, timeout_no_watchers, user_data);
492 }434 }
493435
494 return;436 return;
@@ -534,7 +476,7 @@
534/* Here is the function that gets called by the dbus476/* Here is the function that gets called by the dbus
535 interface "Watch" function. It is an async function so477 interface "Watch" function. It is an async function so
536 that we can get the sender and store that information. We478 that we can get the sender and store that information. We
537 put them in a list and reset the timeout. */479 put them in a list. */
538static GVariant *480static GVariant *
539bus_watch (IndicatorService * service, const gchar * sender)481bus_watch (IndicatorService * service, const gchar * sender)
540{482{
@@ -557,17 +499,11 @@
557 }499 }
558 }500 }
559501
560 if (priv->timeout != 0) {
561 g_source_remove(priv->timeout);
562 priv->timeout = 0;
563 }
564
565 return g_variant_new("(uu)", INDICATOR_SERVICE_VERSION, priv->this_service_version);502 return g_variant_new("(uu)", INDICATOR_SERVICE_VERSION, priv->this_service_version);
566}503}
567504
568/* Performs the core of loosing a watcher; it removes them505/* Performs the core of loosing a watcher; it removes them
569 from the list of watchers. If there are none left, it then506 from the list of watchers. */
570 starts the timer for the shutdown signal. */
571static void507static void
572unwatch_core (IndicatorService * service, const gchar * name)508unwatch_core (IndicatorService * service, const gchar * name)
573{509{
@@ -587,19 +523,6 @@
587 g_warning("Unable to find watcher who is unwatching: %s", name);523 g_warning("Unable to find watcher who is unwatching: %s", name);
588 }524 }
589525
590 /* If we're out of watchers set the timeout for shutdown */
591 if (g_hash_table_size(priv->watchers) == 0) {
592 if (priv->timeout != 0) {
593 /* This should never really happen, but let's ensure that
594 bad things don't happen if it does. */
595 g_warning("No watchers timeout set twice. Resolving, but odd.");
596 g_source_remove(priv->timeout);
597 priv->timeout = 0;
598 }
599 /* If we don't get a new watcher quickly, we'll shutdown. */
600 priv->timeout = g_timeout_add(priv->timeout_length, timeout_no_watchers, service);
601 }
602
603 return;526 return;
604}527}
605528

Subscribers

People subscribed via source and target branches