Merge lp:~stgraber/upstart/upstart-make-event-bridge-usable into lp:upstart

Proposed by Stéphane Graber
Status: Merged
Merged at revision: 1430
Proposed branch: lp:~stgraber/upstart/upstart-make-event-bridge-usable
Merge into: lp:upstart
Diff against target: 168 lines (+58/-17)
2 files modified
extra/conf/upstart-event-bridge.conf (+1/-2)
extra/upstart-event-bridge.c (+57/-15)
To merge this branch: bzr merge lp:~stgraber/upstart/upstart-make-event-bridge-usable
Reviewer Review Type Date Requested Status
James Hunt Approve
Review via email: mp+144399@code.launchpad.net

Description of the change

This branch addresses a few problems with the current implementation of the
event bridge.

== PID file handling ==
In the past, when started with --daemon, nih would try to create a pidfile
under /run, which would obviously fail when running as a user.
The first change is to instead use XDG_RUNTIME_DIR or HOME as the preferred
location for the pidfile.

This brings us to the second problem with the pidfile. A single user may have
multiple upstart instances running at the same time, each of those would
require its own event bridge. So the pidfile can't be unique to the user.

This one was fixed in two ways:
 - upstart-event-bridge.conf no longer uses --daemon, so by default no pidfile
   will be created at all.
 - When called with --daemon, the pidfile now includes the PID of the upstart
   instance, taken from the value of UPSTART_SESSION (last field).

== DBus socket ==
When the event bridge was initially written, we didn't have a private socket
for the user instance, so the bridge was connecting to the DBus session bus.
However, we know have that private socket and no longer use the session bus by
default.

So this branch now changes the default bus from the session bus to the upstart
user session private bus.

To post a comment you must log in.
Revision history for this message
James Hunt (jamesodhunt) wrote :

* extra/upstart-event-bridge.c: main():
  - Looks like user_session_path should be nih_local, whilst path_element should just be 'char *'?
  - If $HOME is not set, we fail to start. That's probably reasonable though as we display a couple
    of errors in that scenario.

review: Needs Fixing
1432. By Stéphane Graber

Change which variables are nih_local and which aren't as that was resulting in segfaults when starting with --daemon.

Revision history for this message
Stéphane Graber (stgraber) wrote :

> * extra/upstart-event-bridge.c: main():
> - Looks like user_session_path should be nih_local, whilst path_element
> should just be 'char *'?

Done. While testing that change, I also noticed a couple more that shouldn't be nih_local as they were causing segfaults in daemon mode. I didn't spot those earlier because I didn't think of running the daemon under strace to catch any potential segfault on exit of the child.

> - If $HOME is not set, we fail to start. That's probably reasonable though
> as we display a couple
> of errors in that scenario.

Right, the only other thing I could think of was trying to write in CWD but if HOME isn't set, it's fairly likely to be somewhere you can't write to anyway (or shouldn't at least).
The main problem here is that libnih doesn't let you use the daemonise function without also creating a pidfile.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

> > - If $HOME is not set, we fail to start. That's probably reasonable though
> > as we display a couple
> > of errors in that scenario.
>
> Right, the only other thing I could think of was trying to write in CWD but if
> HOME isn't set, it's fairly likely to be somewhere you can't write to anyway
> (or shouldn't at least).
> The main problem here is that libnih doesn't let you use the daemonise
> function without also creating a pidfile.

Spam /tmp/ ?! or /run/upstart/ those should be writable.
Even to $HOMEless mere mortals.

Revision history for this message
Stéphane Graber (stgraber) wrote :

/run/upstart shouldn't be user writable. /tmp should work but is really kind of wrong for a pidfile.
So I think I'll stick to the current implementation, which by the way doesn't prevent the daemon from starting at all, it just prints an extra error on the console and doesn't create the pidfile.

Revision history for this message
James Hunt (jamesodhunt) wrote :

Agreed. LGTM - merged.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'extra/conf/upstart-event-bridge.conf'
--- extra/conf/upstart-event-bridge.conf 2013-01-10 18:44:12 +0000
+++ extra/conf/upstart-event-bridge.conf 2013-01-23 19:20:39 +0000
@@ -10,7 +10,6 @@
10start on started dbus10start on started dbus
11stop on stopped dbus11stop on stopped dbus
1212
13expect daemon
14respawn13respawn
1514
16exec upstart-event-bridge --daemon15exec upstart-event-bridge
1716
=== modified file 'extra/upstart-event-bridge.c'
--- extra/upstart-event-bridge.c 2012-12-19 17:02:33 +0000
+++ extra/upstart-event-bridge.c 2013-01-23 19:20:39 +0000
@@ -1,6 +1,6 @@
1/* upstart1/* upstart
2 *2 *
3 * Copyright © 2012 Canonical Ltd.3 * Copyright © 2012-2013 Canonical Ltd.
4 * Author: Stéphane Graber <stgraber@ubuntu.com>4 * Author: Stéphane Graber <stgraber@ubuntu.com>
5 *5 *
6 * This program is free software; you can redistribute it and/or modify6 * This program is free software; you can redistribute it and/or modify
@@ -67,11 +67,11 @@
67static NihDBusProxy *system_upstart = NULL;67static NihDBusProxy *system_upstart = NULL;
6868
69/**69/**
70 * session_upstart:70 * user_upstart:
71 *71 *
72 * Proxy to session Upstart daemon.72 * Proxy to user Upstart daemon instance.
73 **/73 **/
74static NihDBusProxy *session_upstart = NULL;74static NihDBusProxy *user_upstart = NULL;
7575
76/**76/**
77 * options:77 * options:
@@ -92,13 +92,18 @@
92{92{
93 char ** args;93 char ** args;
94 DBusConnection * system_connection;94 DBusConnection * system_connection;
95 DBusConnection * session_connection;95 DBusConnection * user_connection;
96 int ret;96 int ret;
97 char * pidfile_path = NULL;
98 char * pidfile = NULL;
99 char * user_session_addr = NULL;
100 nih_local char ** user_session_path = NULL;
101 char * path_element = NULL;
97102
98103
99 nih_main_init (argv[0]);104 nih_main_init (argv[0]);
100105
101 nih_option_set_synopsis (_("Bridge system upstart events into session upstart"));106 nih_option_set_synopsis (_("Bridge system upstart events into the user session upstart"));
102 nih_option_set_help (107 nih_option_set_help (
103 _("By default, upstart-event-bridge does not detach from the "108 _("By default, upstart-event-bridge does not detach from the "
104 "console and remains in the foreground. Use the --daemon "109 "console and remains in the foreground. Use the --daemon "
@@ -108,6 +113,12 @@
108 if (! args)113 if (! args)
109 exit (1);114 exit (1);
110115
116 user_session_addr = getenv ("UPSTART_SESSION");
117 if (! user_session_addr) {
118 nih_fatal (_("UPSTART_SESSION isn't set in environment"));
119 exit (1);
120 }
121
111 /* Initialise the connection to system Upstart */122 /* Initialise the connection to system Upstart */
112 system_connection = NIH_SHOULD (nih_dbus_bus (DBUS_BUS_SYSTEM, upstart_disconnected));123 system_connection = NIH_SHOULD (nih_dbus_bus (DBUS_BUS_SYSTEM, upstart_disconnected));
113124
@@ -160,24 +171,24 @@
160 exit (1);171 exit (1);
161 }172 }
162173
163 /* Initialise the connection to session Upstart */174 /* Initialise the connection to user session Upstart */
164 session_connection = nih_dbus_bus (DBUS_BUS_SESSION, upstart_disconnected);175 user_connection = NIH_SHOULD (nih_dbus_connect (user_session_addr, upstart_disconnected));
165176
166 if (! session_connection) {177 if (! user_connection) {
167 NihError *err;178 NihError *err;
168179
169 err = nih_error_get ();180 err = nih_error_get ();
170 nih_fatal ("%s: %s", _("Could not connect to session Upstart"),181 nih_fatal ("%s: %s", _("Could not connect to the user session Upstart"),
171 err->message);182 err->message);
172 nih_free (err);183 nih_free (err);
173184
174 exit (1);185 exit (1);
175 }186 }
176187
177 session_upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, session_connection,188 user_upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, user_connection,
178 DBUS_SERVICE_UPSTART, DBUS_PATH_UPSTART,189 NULL, DBUS_PATH_UPSTART,
179 NULL, NULL));190 NULL, NULL));
180 if (! session_upstart) {191 if (! user_upstart) {
181 NihError *err;192 NihError *err;
182193
183 err = nih_error_get ();194 err = nih_error_get ();
@@ -190,6 +201,32 @@
190201
191 /* Become daemon */202 /* Become daemon */
192 if (daemonise) {203 if (daemonise) {
204 /* Deal with the pidfile location when becoming a daemon.
205 * We need to be able to run one bridge per upstart daemon.
206 * Store the PID file in XDG_RUNTIME_DIR or HOME and include the pid of
207 * the Upstart instance (last part of the DBus path) in the filename.
208 */
209
210 /* Extract PID from UPSTART_SESSION */
211 user_session_path = nih_str_split (NULL, user_session_addr, "/", TRUE);
212 for (int i = 0; user_session_path[i] != NULL; i++)
213 path_element = user_session_path[i];
214
215 if (! path_element) {
216 nih_fatal (_("Invalid value for UPSTART_SESSION"));
217 exit (1);
218 }
219
220 pidfile_path = getenv ("XDG_RUNTIME_DIR");
221 if (!pidfile_path)
222 pidfile_path = getenv ("HOME");
223
224 if (pidfile_path) {
225 NIH_MUST (nih_strcat_sprintf (&pidfile, NULL, "%s/upstart-event-bridge.%s.pid",
226 pidfile_path, path_element));
227 nih_main_set_pidfile (pidfile);
228 }
229
193 if (nih_main_daemonise () < 0) {230 if (nih_main_daemonise () < 0) {
194 NihError *err;231 NihError *err;
195232
@@ -213,6 +250,11 @@
213250
214 ret = nih_main_loop ();251 ret = nih_main_loop ();
215252
253 /* Destroy any PID file we may have created */
254 if (daemonise) {
255 nih_main_unlink_pidfile();
256 }
257
216 return ret;258 return ret;
217}259}
218260
@@ -253,7 +295,7 @@
253 NIH_MUST (nih_strcat_sprintf (&new_event_name, NULL, ":sys:%s", event_name));295 NIH_MUST (nih_strcat_sprintf (&new_event_name, NULL, ":sys:%s", event_name));
254296
255 /* Re-transmit the event */297 /* Re-transmit the event */
256 pending_call = upstart_emit_event (session_upstart,298 pending_call = upstart_emit_event (user_upstart,
257 new_event_name, event_env, FALSE,299 new_event_name, event_env, FALSE,
258 NULL, emit_event_error, NULL,300 NULL, emit_event_error, NULL,
259 NIH_DBUS_TIMEOUT_NEVER);301 NIH_DBUS_TIMEOUT_NEVER);
@@ -277,7 +319,7 @@
277 DBusPendingCall * pending_call;319 DBusPendingCall * pending_call;
278320
279 /* Re-transmit the event */321 /* Re-transmit the event */
280 pending_call = upstart_emit_event (session_upstart,322 pending_call = upstart_emit_event (user_upstart,
281 ":sys:restarted", NULL, FALSE,323 ":sys:restarted", NULL, FALSE,
282 NULL, emit_event_error, NULL,324 NULL, emit_event_error, NULL,
283 NIH_DBUS_TIMEOUT_NEVER);325 NIH_DBUS_TIMEOUT_NEVER);

Subscribers

People subscribed via source and target branches