Merge lp:~ted/libindicator/upstart-no-dbus into lp:libindicator/13.10

Proposed by Ted Gould
Status: Work in progress
Proposed branch: lp:~ted/libindicator/upstart-no-dbus
Merge into: lp:libindicator/13.10
Diff against target: 294 lines (+29/-152)
2 files modified
libindicator/indicator-ng.c (+6/-67)
libindicator/indicator-service-manager.c (+23/-85)
To merge this branch: bzr merge lp:~ted/libindicator/upstart-no-dbus
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Indicator Applet Developers Pending
Review via email: mp+166269@code.launchpad.net

Commit message

When running under Upstart session let Upstart manage the service.

Description of the change

When we're running under upstart we want upstart to manage the process lifecycle for the service, not the panel-service. This patch makes it so that when we have an upstart session there isn't any dbus activation attempted. Long term we should be able to assume Upstart user session (default on Saucy) and remove the checking code, but let's keep things usable on Raring for now.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Lars Karlitski (larsu) wrote :

I think having the panel (or anything in the session) being aware of the init daemon is inside-out architecture.

Will every service now have to ship with an upstart script in addition to the dbus service file it already has? That adds an unnecessary dependency, and makes it harder to write services.

Why don't we make upstart aware of dbus activation? (I believe I heard it already is, or will be in the near future?) This will bring us all the benefits of upstart managing the services without any extra work.

Are there any advantages to using upstart explicitly?

Revision history for this message
Ted Gould (ted) wrote :

On Wed, 2013-05-29 at 15:51 +0000, Lars Uebernickel wrote:

> I think having the panel (or anything in the session) being aware of
> the init daemon is inside-out architecture.

It's not the init daemon in this case. It's the session manager. It's
like being aware that there is a gnome-session.

> Will every service now have to ship with an upstart script in addition
> to the dbus service file it already has? That adds an unnecessary
> dependency, and makes it harder to write services.

No, there'll be no reason to ship a dbus service file.

> Why don't we make upstart aware of dbus activation? (I believe I heard
> it already is, or will be in the near future?) This will bring us all
> the benefits of upstart managing the services without any extra work.
>
> Are there any advantages to using upstart explicitly?

There was a patch for that, it was rejected upstream, we may put it back
in Ubuntu. But, even with that using Upstart jobs is better for
indicators. It keeps the log files in a single file that is
automatically picked up by apport and attached to bugs. Upstart can
restart the service including retry intervals. And for developers they
can manage when the service stops and starts with external tools that
already exist.

Revision history for this message
Lars Karlitski (larsu) wrote :

> On Wed, 2013-05-29 at 15:51 +0000, Lars Uebernickel wrote:
>
> > I think having the panel (or anything in the session) being aware of
> > the init daemon is inside-out architecture.
>
> It's not the init daemon in this case. It's the session manager. It's
> like being aware that there is a gnome-session.

Right. But I don't see why it should be aware of the session service, either.

> > Will every service now have to ship with an upstart script in addition
> > to the dbus service file it already has? That adds an unnecessary
> > dependency, and makes it harder to write services.
>
> No, there'll be no reason to ship a dbus service file.
>
> > Why don't we make upstart aware of dbus activation? (I believe I heard
> > it already is, or will be in the near future?) This will bring us all
> > the benefits of upstart managing the services without any extra work.
> >
> > Are there any advantages to using upstart explicitly?
>
> There was a patch for that, it was rejected upstream, we may put it back
> in Ubuntu. But, even with that using Upstart jobs is better for
> indicators. It keeps the log files in a single file that is
> automatically picked up by apport and attached to bugs. Upstart can
> restart the service including retry intervals. And for developers they
> can manage when the service stops and starts with external tools that
> already exist.

All of these things will be true anyway, because upstart *is* managing the services.

Revision history for this message
Ted Gould (ted) wrote :

On Wed, 2013-05-29 at 16:18 +0000, Lars Uebernickel wrote:

> All of these things will be true anyway, because upstart *is* managing
> the services.

I guess, but I'm not sure why you're concerned over the job
configuration having:

  start on dbus-activation com.canonical.indicator.network

versus

  start on indicators-loaded

It seems like the second one is clearer and can be managed more easily
as we'll be able to introspect the startup with things like initctl2dot.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~ted/libindicator/upstart-no-dbus updated
492. By Ted Gould

Don't make the service manager do DBus activation in the Upstart session case.

493. By Ted Gould

Merging trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Lars Karlitski (larsu) wrote :

> On Wed, 2013-05-29 at 16:18 +0000, Lars Uebernickel wrote:
>
> > All of these things will be true anyway, because upstart *is* managing
> > the services.
>
>
> I guess, but I'm not sure why you're concerned over the job
> configuration having:
>
> start on dbus-activation com.canonical.indicator.network
>
> versus
>
> start on indicators-loaded
>
> It seems like the second one is clearer and can be managed more easily
> as we'll be able to introspect the startup with things like initctl2dot.

My point is that the first one won't be needed. Upstart should just take control over all dbus-activated things in the session.

Revision history for this message
Ted Gould (ted) wrote :

On Thu, 2013-05-30 at 12:17 +0000, Lars Uebernickel wrote:

> My point is that the first one won't be needed. Upstart should just
> take control over all dbus-activated things in the session.

I don't think that it'll "take over" all of them because my
understanding is that for Upstart, dbus activation is an event type not
a job.

Revision history for this message
Ted Gould (ted) wrote :

At the end of the day, it comes down to upstart being a process manager. Sure, we could use dbus activation, but then the panel service becomes the process manager. Let's leave process management to a tool that is designed to do that job (and does it well).

lp:~ted/libindicator/upstart-no-dbus updated
494. By Ted Gould

Only build the calcelable if we've got a name

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~ted/libindicator/upstart-no-dbus updated
495. By Ted Gould

Update to trunk

496. By Ted Gould

Kill the restart code

497. By Ted Gould

Remove the callback

498. By Ted Gould

Assume Upstart in the manager code

499. By Ted Gould

Drop the restartarting the service code

500. By Ted Gould

Don't unwatch on error, we still want to watch for a new one starting

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

I object to this. upstart is not mandatory to manage desktop session on ubuntu. And indicators are used on the desktop sessions which are not managed by upstart. At the moment upstart as a user session manager, is opt-in, not opt-out on per session type as defined in /etc/upstart-xsessions. Thus one should preserve dbus activation files.

I understand the desire to have dbus services be managed/respawned by upstart the session manager, but forcing that to happen is not the right solution.

Unmerged revisions

500. By Ted Gould

Don't unwatch on error, we still want to watch for a new one starting

499. By Ted Gould

Drop the restartarting the service code

498. By Ted Gould

Assume Upstart in the manager code

497. By Ted Gould

Remove the callback

496. By Ted Gould

Kill the restart code

495. By Ted Gould

Update to trunk

494. By Ted Gould

Only build the calcelable if we've got a name

493. By Ted Gould

Merging trunk

492. By Ted Gould

Don't make the service manager do DBus activation in the Upstart session case.

491. By Ted Gould

Don't start the service when we're under the Upstart session

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libindicator/indicator-ng.c'
2--- libindicator/indicator-ng.c 2013-06-28 18:30:33 +0000
3+++ libindicator/indicator-ng.c 2013-08-05 14:54:23 +0000
4@@ -390,44 +390,9 @@
5 indicator_ng_update_entry (self);
6 }
7
8-static void
9-indicator_ng_service_started (GObject *source_object,
10- GAsyncResult *res,
11- gpointer user_data)
12-{
13- IndicatorNg *self = user_data;
14- GError *error = NULL;
15- GVariant *result;
16- guint32 start_service_reply;
17-
18- result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error);
19- if (!result)
20- {
21- g_warning ("Could not activate service '%s': %s", self->name, error->message);
22- indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE);
23- g_error_free (error);
24- return;
25- }
26-
27- start_service_reply = 0;
28- g_variant_get (result, "(u)", &start_service_reply);
29-
30- switch (start_service_reply)
31- {
32- case 1: /* DBUS_START_REPLY_SUCCESS */
33- break;
34-
35- case 2: /* DBUS_START_REPLY_ALREADY_RUNNING */
36- g_warning ("could not start service '%s': it is already running", self->name);
37- break;
38-
39- default:
40- g_assert_not_reached ();
41- }
42-
43- g_variant_unref (result);
44-}
45-
46+/* This function gets called everytime a service matching an
47+ indicator file vanishes from dbus. It cleans up and sets
48+ it up again to be ready when it comes back. */
49 static void
50 indicator_ng_service_vanished (GDBusConnection *connection,
51 const gchar *name,
52@@ -437,34 +402,7 @@
53
54 indicator_ng_free_actions_and_menu (self);
55
56- /* Names may vanish because the service decided it doesn't need to
57- * show its indicator anymore, or because it crashed. Let's assume it
58- * crashes and restart it unless it explicitly hid its indicator. */
59-
60- if (indicator_object_entry_is_visible (INDICATOR_OBJECT (self), &self->entry))
61- {
62- gint64 now;
63-
64- /* take care not to start it if it repeatedly crashes */
65- now = g_get_monotonic_time ();
66- if (now - self->last_service_restart < 1 * G_USEC_PER_SEC)
67- return;
68-
69- self->last_service_restart = now;
70-
71- g_dbus_connection_call (self->session_bus,
72- "org.freedesktop.DBus",
73- "/",
74- "org.freedesktop.DBus",
75- "StartServiceByName",
76- g_variant_new ("(su)", self->bus_name, 0),
77- G_VARIANT_TYPE ("(u)"),
78- G_DBUS_CALL_FLAGS_NONE,
79- -1,
80- NULL,
81- indicator_ng_service_started,
82- self);
83- }
84+ return;
85 }
86
87 /* Get an integer from a keyfile. Returns @default_value if the key
88@@ -534,6 +472,7 @@
89 self->bus_name = g_path_get_basename (self->service_file);
90
91 keyfile = g_key_file_new ();
92+
93 if (g_key_file_load_from_file (keyfile, self->service_file, G_KEY_FILE_NONE, error) &&
94 indicator_ng_load_from_keyfile (self, keyfile, error))
95 {
96@@ -544,7 +483,7 @@
97 {
98 self->name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
99 self->bus_name,
100- G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
101+ G_BUS_NAME_WATCHER_FLAGS_NONE,
102 indicator_ng_service_appeared,
103 indicator_ng_service_vanished,
104 self, NULL);
105
106=== modified file 'libindicator/indicator-service-manager.c'
107--- libindicator/indicator-service-manager.c 2012-07-12 15:44:39 +0000
108+++ libindicator/indicator-service-manager.c 2013-08-05 14:54:23 +0000
109@@ -100,7 +100,6 @@
110 static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
111 static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
112 static void start_service (IndicatorServiceManager * service);
113-static void start_service_again (IndicatorServiceManager * manager);
114 static void unwatch (GDBusProxy * proxy);
115 static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
116 static void service_proxy_name_changed (GDBusConnection * connection, const gchar * sender_name, const gchar * object_path, const gchar * interface_name, const gchar * signal_name, GVariant * parameters, gpointer user_data);
117@@ -370,7 +369,6 @@
118 if (error != NULL) {
119 g_warning("Unable to set watch on '%s': '%s'", priv->name, error->message);
120 g_error_free(error);
121- start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
122 return;
123 }
124
125@@ -388,21 +386,11 @@
126
127 if (service_api_version != INDICATOR_SERVICE_VERSION) {
128 g_warning("Service is using a different version of the service interface. Expecting %d and got %d.", INDICATOR_SERVICE_VERSION, service_api_version);
129- unwatch(priv->service_proxy);
130-
131- /* Let's make us wait a little while, then try again */
132- priv->restart_count = TIMEOUT_A_LITTLE_WHILE;
133- start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
134 return;
135 }
136
137 if (this_service_version != priv->this_service_version) {
138 g_warning("Service is using a different API version than the manager. Expecting %d and got %d.", priv->this_service_version, this_service_version);
139- unwatch(priv->service_proxy);
140-
141- /* Let's make us wait a little while, then try again */
142- priv->restart_count = TIMEOUT_A_LITTLE_WHILE;
143- start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
144 return;
145 }
146
147@@ -437,8 +425,11 @@
148
149 priv->service_proxy_cancel = g_cancellable_new();
150
151+ /* Ugly code. Basically if Upstart is managing the lifecycle of the
152+ service we shouldn't do it for it. This should go away as soon as
153+ we can assume that we're always in an Upstart desktop session. (Saucy) */
154 g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
155- G_DBUS_PROXY_FLAGS_NONE,
156+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
157 interface_info,
158 priv->name,
159 INDICATOR_SERVICE_OBJECT,
160@@ -474,20 +465,10 @@
161 /* Unable to create the proxy, eh, let's try again
162 in a bit */
163 g_error_free(error);
164- start_service_again(service);
165 return;
166 }
167
168 gchar * name = g_dbus_proxy_get_name_owner(proxy);
169- if (name == NULL) {
170- /* Hmm, since creating the proxy should start it, it seems very
171- odd that it wouldn't have an owner at this point. But, all
172- we can do is try again. */
173- g_object_unref(proxy);
174- start_service_again(service);
175- return;
176- }
177- g_free(name);
178
179 /* Okay, we're good to grab the proxy at this point, we're
180 sure that it's ours. */
181@@ -506,20 +487,24 @@
182 user_data,
183 NULL);
184
185- /* Build cancelable if we need it */
186- if (priv->watch_cancel == NULL) {
187- priv->watch_cancel = g_cancellable_new();
188+ /* Send watch if someone is there */
189+ if (name != NULL) {
190+ /* Build cancelable if we need it */
191+ if (priv->watch_cancel == NULL) {
192+ priv->watch_cancel = g_cancellable_new();
193+ }
194+
195+ g_dbus_proxy_call(priv->service_proxy,
196+ "Watch",
197+ NULL, /* params */
198+ G_DBUS_CALL_FLAGS_NONE,
199+ -1,
200+ priv->watch_cancel,
201+ watch_cb,
202+ user_data);
203 }
204
205- /* Send watch */
206- g_dbus_proxy_call(priv->service_proxy,
207- "Watch",
208- NULL, /* params */
209- G_DBUS_CALL_FLAGS_NONE,
210- -1,
211- priv->watch_cancel,
212- watch_cb,
213- user_data);
214+ g_free(name);
215
216 return;
217 }
218@@ -545,8 +530,6 @@
219 priv->connected = FALSE;
220 g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, FALSE, TRUE);
221 }
222-
223- start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
224 } else {
225 /* If we weren't connected before, we are now. Let's tell the
226 world! */
227@@ -555,10 +538,12 @@
228 g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE);
229 }
230
231+ /* First check to see if this is a new service getting the name, if that's
232+ the case, watch it. */
233 /* If the names are both valid, and they're not the same, it means that
234 we've actually changed. So we need to tell the new guy that we're
235 watching them */
236- if (new_name != NULL && prev_name != NULL && new_name[0] != 0 && prev_name != 0 && g_strcmp0(prev_name, new_name) != 0) {
237+ if (prev_name == NULL || (new_name != NULL && prev_name != NULL && new_name[0] != 0 && prev_name != 0 && g_strcmp0(prev_name, new_name) != 0)) {
238 /* Send watch */
239 g_dbus_proxy_call(priv->service_proxy,
240 "Watch",
241@@ -574,53 +559,6 @@
242 return;
243 }
244
245-/* The callback that starts the service for real after
246- the timeout as determined in 'start_service_again'.
247- This could be in the idle or a timer. */
248-static gboolean
249-start_service_again_cb (gpointer data)
250-{
251- IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(data);
252- priv->restart_count++;
253- g_debug("Restarting service '%s' count %d", priv->name, priv->restart_count);
254- start_service(INDICATOR_SERVICE_MANAGER(data));
255- priv->restart_source = 0;
256- return FALSE;
257-}
258-
259-/* This function tries to start a new service, perhaps
260- after a timeout that it determines. The real issue
261- here is that it throttles restarting if we're not
262- being successful. */
263-static void
264-start_service_again (IndicatorServiceManager * manager)
265-{
266- IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(manager);
267-
268- /* If we've already got a restart source running then
269- let's not do this again. */
270- if (priv->restart_source != 0) {
271- return;
272- }
273-
274- /* Allow the restarting to be disabled */
275- if (g_getenv(TIMEOUT_ENV_NAME)) {
276- return;
277- }
278-
279- if (priv->restart_count == 0) {
280- /* First time, do it in idle */
281- g_idle_add(start_service_again_cb, manager);
282- } else {
283- /* Not our first time 'round the block. Let's slow this down. */
284- if (priv->restart_count > 16)
285- priv->restart_count = 16; /* Not more than 1024x */
286- priv->restart_source = g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager);
287- }
288-
289- return;
290-}
291-
292 /* API */
293
294 /**

Subscribers

People subscribed via source and target branches