Merge lp:~stgraber/upstart/upstart-events-bridge into lp:upstart

Proposed by Stéphane Graber
Status: Merged
Merged at revision: 1421
Proposed branch: lp:~stgraber/upstart/upstart-events-bridge
Merge into: lp:upstart
Diff against target: 444 lines (+405/-2)
4 files modified
extra/Makefile.am (+17/-2)
extra/conf/upstart-event-bridge.conf (+16/-0)
extra/man/upstart-event-bridge.8 (+68/-0)
extra/upstart-event-bridge.c (+304/-0)
To merge this branch: bzr merge lp:~stgraber/upstart/upstart-events-bridge
Reviewer Review Type Date Requested Status
James Hunt Approve
Review via email: mp+140693@code.launchpad.net

Description of the change

This introduces a new upstart-event-bridge, started once dbus is start in
the user session and which then relays events from the system upstart to the
session upstart.

Events are all prefixed with ":sys:" and a special even also exists for when
the system upstart is restarted (":sys:restarted").

Testing was only done with the current upstart listening to the session bus,
but it should still work fine once we have the full user session support
implemented.

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

* extra/man/upstart-event-bridge.8:
  - 'See events(7)' should be upstart-events(7).
  - Can you mention that this should (generally) run as a non-priv user, 1 per Session Init.
* extra/upstart-event-bridge.c: I'm wondering if we want to not forward output to syslog in the daemonise case? Users may prefer to have the output logged to ~/.cache/upstart/upstart-event-bridge.log.

1418. By Stéphane Graber

Update manpage

1419. By Stéphane Graber

Remove logging to syslog

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

LGTM - merged.

review: Approve
Revision history for this message
Steve Langasek (vorlon) wrote :

On Wed, Dec 19, 2012 at 02:55:24PM -0000, Stéphane Graber wrote:
> This introduces a new upstart-event-bridge, started once dbus is start in
> the user session and which then relays events from the system upstart to the
> session upstart.

> Events are all prefixed with ":sys:" and a special even also exists for when
> the system upstart is restarted (":sys:restarted").

> Testing was only done with the current upstart listening to the session bus,
> but it should still work fine once we have the full user session support
> implemented.

What's the rationale for implementing this over the user dbus, instead of
having the user session's init process connecting to upstart directly? dbus
looks like needless indirection here to me.

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

Because it's the only way to catch the Restarted event. If we connected to the upstart system socket instead (assuming we can as a user, haven't checked), we'd loose the connection and have to reconnect, most likely loosing the Restarted event in the process.

Revision history for this message
Steve Langasek (vorlon) wrote :

On Wed, Dec 19, 2012 at 06:03:28PM -0000, Stéphane Graber wrote:

> Because it's the only way to catch the Restarted event. If we connected to
> the upstart system socket instead (assuming we can as a user, haven't
> checked), we'd loose the connection and have to reconnect, most likely
> loosing the Restarted event in the process.

Sorry, what I meant was, why are we using dbus on the *user session* side?
The user session init should be able to connect directly to the system bus,
with no need for this separate bridge process that's dependent on having a
session bus running.

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

Ah right, well, we figured it was the easiest way to implement it, would make it much easier to support scenario where we use upstart for the user session but not for the system itself (thinking of Debian there). I vaguely remember something else being mentioned, maybe James can refresh my memory there.

For the session bus, that part should be easy to improve by using upstart's own socket for the user session. This feature doesn't exist yet though so I could use it. It's on my todo for tomorrow, so after that I should be able to avoid using the session bus.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'extra/Makefile.am'
2--- extra/Makefile.am 2011-06-06 15:49:43 +0000
3+++ extra/Makefile.am 2012-12-19 17:07:26 +0000
4@@ -17,13 +17,16 @@
5
6
7 sbin_PROGRAMS = \
8- upstart-socket-bridge
9+ upstart-socket-bridge \
10+ upstart-event-bridge
11
12 dist_init_DATA = \
13- conf/upstart-socket-bridge.conf
14+ conf/upstart-socket-bridge.conf \
15+ conf/upstart-event-bridge.conf
16
17 dist_man_MANS = \
18 man/upstart-socket-bridge.8 \
19+ man/upstart-event-bridge.8 \
20 man/socket-event.7
21
22 upstart_socket_bridge_SOURCES = \
23@@ -37,6 +40,18 @@
24 $(NIH_DBUS_LIBS) \
25 $(DBUS_LIBS)
26
27+upstart_event_bridge_SOURCES = \
28+ upstart-event-bridge.c
29+nodist_upstart_event_bridge_SOURCES = \
30+ $(com_ubuntu_Upstart_OUTPUTS) \
31+ $(com_ubuntu_Upstart_Job_OUTPUTS)
32+upstart_event_bridge_LDADD = \
33+ $(LTLIBINTL) \
34+ $(NIH_LIBS) \
35+ $(NIH_DBUS_LIBS) \
36+ $(DBUS_LIBS)
37+
38+
39
40 if HAVE_UDEV
41 dist_init_DATA += \
42
43=== added file 'extra/conf/upstart-event-bridge.conf'
44--- extra/conf/upstart-event-bridge.conf 1970-01-01 00:00:00 +0000
45+++ extra/conf/upstart-event-bridge.conf 2012-12-19 17:07:26 +0000
46@@ -0,0 +1,16 @@
47+# upstart-events-bridge - Bridge system upstarts events into session upstart
48+#
49+# This helper daemon receives system upstart events from the DBus system bus
50+# and emits equivalent events (with a :sys:) prefix to the session bus
51+
52+description "Bridge Upstart system events into session Upstart"
53+
54+emits :sys:*
55+
56+start on started dbus
57+stop on stopped dbus
58+
59+expect daemon
60+respawn
61+
62+exec upstart-events-bridge --daemon
63
64=== added file 'extra/man/upstart-event-bridge.8'
65--- extra/man/upstart-event-bridge.8 1970-01-01 00:00:00 +0000
66+++ extra/man/upstart-event-bridge.8 2012-12-19 17:07:26 +0000
67@@ -0,0 +1,68 @@
68+.TH upstart\-events\-bridge 8 2011-03-08 upstart
69+.\"
70+.SH NAME
71+upstart\-events\-bridge \- Bridge between system Upstart and session Upstart
72+.\"
73+.SH SYNOPSIS
74+.B upstart\-events\-bridge
75+.RI [ OPTIONS ]...
76+.\"
77+.SH DESCRIPTION
78+.B upstart\-events\-bridge
79+receives information about Upstart system
80+.BR events (8)
81+have completed and creates Upstart session events for them.
82+
83+It emits events which match the pattern ":sys:*". Forwarding any event that's
84+triggered on the system upstart as well as a virtual "restarted" event when
85+upstart itself is restarted (during upgrades).
86+
87+See \fBupstart-events\fP(7) and for further details.
88+
89+This bridge should be run as a user, after the session bus has been setup and
90+only once per session init.
91+
92+.\"
93+.SH OPTIONS
94+.\"
95+.TP
96+.B \-\-daemon
97+Detach and run in the background.
98+.\"
99+.TP
100+.B \-\-debug
101+Enable debugging output.
102+.\"
103+.TP
104+.B \-\-help
105+Show brief usage summary.
106+.\"
107+.TP
108+.B \-\-verbose
109+Enable verbose output.
110+.\"
111+.SH EXAMPLES
112+
113+Some examples of Upstart events generated by this bridge:
114+.IP :sys:restarted
115+Event emitted when the system Upstart is restarted.
116+.IP :sys:*
117+Any event emitted on the system Upstart.
118+.\"
119+.SH AUTHOR
120+Written by Stéphane Graber
121+.RB < stgraber@ubuntu.com >
122+.\"
123+.SH BUGS
124+Report bugs at
125+.RB < https://launchpad.net/ubuntu/+source/upstart/+bugs >
126+.\"
127+.SH COPYRIGHT
128+Copyright \(co 2012 Canonical Ltd.
129+.PP
130+This is free software; see the source for copying conditions. There is NO
131+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
132+.SH SEE ALSO
133+.BR init (5)
134+.BR init (8)
135+.BR events (7)
136
137=== added file 'extra/upstart-event-bridge.c'
138--- extra/upstart-event-bridge.c 1970-01-01 00:00:00 +0000
139+++ extra/upstart-event-bridge.c 2012-12-19 17:07:26 +0000
140@@ -0,0 +1,304 @@
141+/* upstart
142+ *
143+ * Copyright © 2012 Canonical Ltd.
144+ * Author: Stéphane Graber <stgraber@ubuntu.com>
145+ *
146+ * This program is free software; you can redistribute it and/or modify
147+ * it under the terms of the GNU General Public License version 2, as
148+ * published by the Free Software Foundation.
149+ *
150+ * This program is distributed in the hope that it will be useful,
151+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
152+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
153+ * GNU General Public License for more details.
154+ *
155+ * You should have received a copy of the GNU General Public License along
156+ * with this program; if not, write to the Free Software Foundation, Inc.,
157+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
158+ */
159+
160+#ifdef HAVE_CONFIG_H
161+# include <config.h>
162+#endif /* HAVE_CONFIG_H */
163+
164+
165+#include <stdio.h>
166+#include <stdlib.h>
167+#include <string.h>
168+#include <ctype.h>
169+
170+#include <nih/macros.h>
171+#include <nih/alloc.h>
172+#include <nih/string.h>
173+#include <nih/io.h>
174+#include <nih/option.h>
175+#include <nih/main.h>
176+#include <nih/logging.h>
177+#include <nih/error.h>
178+
179+#include <nih-dbus/dbus_connection.h>
180+#include <nih-dbus/dbus_proxy.h>
181+
182+#include "dbus/upstart.h"
183+#include "com.ubuntu.Upstart.h"
184+
185+
186+/* Prototypes for static functions */
187+static void upstart_disconnected (DBusConnection *connection);
188+static void upstart_forward_event (void *data, NihDBusMessage *message,
189+ const char *path);
190+static void upstart_forward_restarted (void *data, NihDBusMessage *message,
191+ const char *path);
192+static void emit_event_error (void *data, NihDBusMessage *message);
193+
194+/**
195+ * daemonise:
196+ *
197+ * Set to TRUE if we should become a daemon, rather than just running
198+ * in the foreground.
199+ **/
200+static int daemonise = FALSE;
201+
202+/**
203+ * system_upstart:
204+ *
205+ * Proxy to system Upstart daemon.
206+ **/
207+static NihDBusProxy *system_upstart = NULL;
208+
209+/**
210+ * session_upstart:
211+ *
212+ * Proxy to session Upstart daemon.
213+ **/
214+static NihDBusProxy *session_upstart = NULL;
215+
216+/**
217+ * options:
218+ *
219+ * Command-line options accepted by this program.
220+ **/
221+static NihOption options[] = {
222+ { 0, "daemon", N_("Detach and run in the background"),
223+ NULL, NULL, &daemonise, NULL },
224+
225+ NIH_OPTION_LAST
226+};
227+
228+
229+int
230+main (int argc,
231+ char *argv[])
232+{
233+ char ** args;
234+ DBusConnection * system_connection;
235+ DBusConnection * session_connection;
236+ int ret;
237+
238+
239+ nih_main_init (argv[0]);
240+
241+ nih_option_set_synopsis (_("Bridge system upstart events into session upstart"));
242+ nih_option_set_help (
243+ _("By default, upstart-event-bridge does not detach from the "
244+ "console and remains in the foreground. Use the --daemon "
245+ "option to have it detach."));
246+
247+ args = nih_option_parser (NULL, argc, argv, options, FALSE);
248+ if (! args)
249+ exit (1);
250+
251+ /* Initialise the connection to system Upstart */
252+ system_connection = NIH_SHOULD (nih_dbus_bus (DBUS_BUS_SYSTEM, upstart_disconnected));
253+
254+ if (! system_connection) {
255+ NihError *err;
256+
257+ err = nih_error_get ();
258+ nih_fatal ("%s: %s", _("Could not connect to system Upstart"),
259+ err->message);
260+ nih_free (err);
261+
262+ exit (1);
263+ }
264+
265+ system_upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, system_connection,
266+ DBUS_SERVICE_UPSTART, DBUS_PATH_UPSTART,
267+ NULL, NULL));
268+ if (! system_upstart) {
269+ NihError *err;
270+
271+ err = nih_error_get ();
272+ nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
273+ err->message);
274+ nih_free (err);
275+
276+ exit (1);
277+ }
278+
279+ if (! nih_dbus_proxy_connect (system_upstart, &upstart_com_ubuntu_Upstart0_6, "EventEmitted",
280+ (NihDBusSignalHandler)upstart_forward_event, NULL)) {
281+ NihError *err;
282+
283+ err = nih_error_get ();
284+ nih_fatal ("%s: %s", _("Could not create EventEmitted signal connection"),
285+ err->message);
286+ nih_free (err);
287+
288+ exit (1);
289+ }
290+
291+ if (! nih_dbus_proxy_connect (system_upstart, &upstart_com_ubuntu_Upstart0_6, "Restarted",
292+ (NihDBusSignalHandler)upstart_forward_restarted, NULL)) {
293+ NihError *err;
294+
295+ err = nih_error_get ();
296+ nih_fatal ("%s: %s", _("Could not create Restarted signal connection"),
297+ err->message);
298+ nih_free (err);
299+
300+ exit (1);
301+ }
302+
303+ /* Initialise the connection to session Upstart */
304+ session_connection = nih_dbus_bus (DBUS_BUS_SESSION, upstart_disconnected);
305+
306+ if (! session_connection) {
307+ NihError *err;
308+
309+ err = nih_error_get ();
310+ nih_fatal ("%s: %s", _("Could not connect to session Upstart"),
311+ err->message);
312+ nih_free (err);
313+
314+ exit (1);
315+ }
316+
317+ session_upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, session_connection,
318+ DBUS_SERVICE_UPSTART, DBUS_PATH_UPSTART,
319+ NULL, NULL));
320+ if (! session_upstart) {
321+ NihError *err;
322+
323+ err = nih_error_get ();
324+ nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
325+ err->message);
326+ nih_free (err);
327+
328+ exit (1);
329+ }
330+
331+ /* Become daemon */
332+ if (daemonise) {
333+ if (nih_main_daemonise () < 0) {
334+ NihError *err;
335+
336+ err = nih_error_get ();
337+ nih_fatal ("%s: %s", _("Unable to become daemon"),
338+ err->message);
339+ nih_free (err);
340+
341+ exit (1);
342+ }
343+ }
344+
345+ /* Handle TERM and INT signals gracefully */
346+ nih_signal_set_handler (SIGTERM, nih_signal_handler);
347+ NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
348+
349+ if (! daemonise) {
350+ nih_signal_set_handler (SIGINT, nih_signal_handler);
351+ NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
352+ }
353+
354+ ret = nih_main_loop ();
355+
356+ return ret;
357+}
358+
359+static void
360+upstart_disconnected (DBusConnection *connection)
361+{
362+ nih_fatal (_("Disconnected from Upstart"));
363+ nih_main_loop_exit (1);
364+}
365+
366+static void
367+upstart_forward_event (void * data,
368+ NihDBusMessage *message,
369+ const char * path)
370+{
371+ char * event_name = NULL;
372+ nih_local char * new_event_name = NULL;
373+ char ** event_env = NULL;
374+ int event_env_count = 0;
375+ DBusError error;
376+ DBusPendingCall * pending_call;
377+
378+ dbus_error_init (&error);
379+
380+ /* Extract information from the original event */
381+ if (!dbus_message_get_args (message->message, &error,
382+ DBUS_TYPE_STRING, &event_name,
383+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &event_env, &event_env_count,
384+ DBUS_TYPE_INVALID)) {
385+ nih_error("DBUS error: %s", error.message);
386+ dbus_error_free(&error);
387+ return;
388+ }
389+
390+ nih_assert (event_name != NULL);
391+
392+ /* Build the new event name */
393+ NIH_MUST (nih_strcat_sprintf (&new_event_name, NULL, ":sys:%s", event_name));
394+
395+ /* Re-transmit the event */
396+ pending_call = upstart_emit_event (session_upstart,
397+ new_event_name, event_env, FALSE,
398+ NULL, emit_event_error, NULL,
399+ NIH_DBUS_TIMEOUT_NEVER);
400+
401+ if (! pending_call) {
402+ NihError *err;
403+ err = nih_error_get ();
404+ nih_warn ("%s", err->message);
405+ nih_free (err);
406+ }
407+
408+ dbus_pending_call_unref (pending_call);
409+ dbus_free_string_array (event_env);
410+}
411+
412+static void
413+upstart_forward_restarted (void * data,
414+ NihDBusMessage *message,
415+ const char * path)
416+{
417+ DBusPendingCall * pending_call;
418+
419+ /* Re-transmit the event */
420+ pending_call = upstart_emit_event (session_upstart,
421+ ":sys:restarted", NULL, FALSE,
422+ NULL, emit_event_error, NULL,
423+ NIH_DBUS_TIMEOUT_NEVER);
424+
425+ if (! pending_call) {
426+ NihError *err;
427+ err = nih_error_get ();
428+ nih_warn ("%s", err->message);
429+ nih_free (err);
430+ }
431+
432+ dbus_pending_call_unref (pending_call);
433+}
434+
435+static void
436+emit_event_error (void * data,
437+ NihDBusMessage *message)
438+{
439+ NihError *err;
440+
441+ err = nih_error_get ();
442+ nih_warn ("%s", err->message);
443+ nih_free (err);
444+}

Subscribers

People subscribed via source and target branches