Merge lp:~xnox/upstart/systemd-local-bridge into lp:ubuntu/vivid/upstart
- systemd-local-bridge
- Merge into vivid
Proposed by
Dimitri John Ledkov
Status: | Merged |
---|---|
Merged at revision: | 1605 |
Proposed branch: | lp:~xnox/upstart/systemd-local-bridge |
Merge into: | lp:ubuntu/vivid/upstart |
Diff against target: |
1265 lines (+636/-233) (has conflicts) 15 files modified
ChangeLog (+12/-0) debian/changelog (+21/-1) debian/control (+2/-2) debian/rules (+0/-1) debian/upstart-bin.install (+4/-0) debian/upstart.install (+0/-4) extra/Makefile.am (+40/-4) extra/com.ubuntu.Upstart.xml (+29/-0) extra/conf-session/upstart-udev-bridge.conf (+22/-0) extra/conf/upstart-event-bridge.conf (+0/-15) extra/org.freedesktop.systemd1.xml (+19/-0) extra/upstart-event-bridge.c (+40/-4) extra/upstart-local-bridge.c (+322/-181) extra/upstart-udev-bridge.c (+63/-5) util/telinit.c (+62/-16) Text conflict in debian/changelog |
To merge this branch: | bzr merge lp:~xnox/upstart/systemd-local-bridge |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Hunt | Pending | ||
Ubuntu branches | Pending | ||
Review via email: mp+246772@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 1599. By Dimitri John Ledkov
-
* debian/
upstart- bin.upstart. cron.daily: Emit "rotate-logs" event direct
into session init, by-passing system upstart & session
* extra/upstart-local-bridge: implement systemd pid1 logic.
* extra/upstart-event-bridge: make it re-emit upstart- local-bridge
events direct.
* util/telinit: Revert to synchronous behaviour coupled with unavoidable
poll to ensure telinit only returns once a re-exec has completed (LP:
#901038). - 1600. By Dimitri John Ledkov
-
Add control xml bindings.
- 1601. By Dimitri John Ledkov
-
Drop event-bridge
- 1602. By Dimitri John Ledkov
-
move udev & local bridges to upstart-bin package.
- 1603. By Dimitri John Ledkov
-
Drop local option, use systemd_booted detection instead.
- 1604. By Dimitri John Ledkov
-
releasing package upstart version 1.13.2-0ubuntu6
- 1605. By Dimitri John Ledkov
-
Correct upstart-udev-bridge session job start/stop on conditions.
Revision history for this message
Dimitri John Ledkov (xnox) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2014-09-04 11:29:54 +0000 |
3 | +++ ChangeLog 2015-01-17 15:39:44 +0000 |
4 | @@ -1,3 +1,15 @@ |
5 | +2014-09-08 James Hunt <james.hunt@ubuntu.com> |
6 | + |
7 | + * util/telinit.c: Remove UPSTART_TELINIT_U_NO_WAIT check as it |
8 | + shouldn't realistically be needed. |
9 | + |
10 | +2014-08-21 James Hunt <james.hunt@ubuntu.com> |
11 | + |
12 | + * util/telinit.c: restart_upstart(): |
13 | + - Revert to synchronous behaviour coupled with unavoidable |
14 | + poll to ensure telinit only returns once a re-exec has |
15 | + completed (LP: #901038). |
16 | + |
17 | 2014-09-04 James Hunt <james.hunt@ubuntu.com> |
18 | |
19 | * NEWS: Release 1.13.2 |
20 | |
21 | === modified file 'debian/changelog' |
22 | --- debian/changelog 2015-01-16 19:15:46 +0000 |
23 | +++ debian/changelog 2015-01-17 15:39:44 +0000 |
24 | @@ -1,13 +1,33 @@ |
25 | +<<<<<<< TREE |
26 | upstart (1.13.2-0ubuntu6) UNRELEASED; urgency=medium |
27 | |
28 | * debian/upstart-bin.upstart.cron.daily: Emit "rotate-logs" event direct |
29 | into session init, by-passing system upstart & session |
30 | +======= |
31 | +upstart (1.13.2-0ubuntu7) UNRELEASED; urgency=medium |
32 | + |
33 | + * Correct upstart-udev-bridge session job start/stop on conditions. |
34 | + |
35 | + -- Dimitri John Ledkov <dimitri.j.ledkov@linux.intel.com> Sat, 17 Jan 2015 15:38:35 +0000 |
36 | + |
37 | +upstart (1.13.2-0ubuntu6) vivid; urgency=medium |
38 | + |
39 | + * debian/upstart-bin.upstart.cron.daily: Emit "rotate-logs" event direct |
40 | + into session init, by-passing system upstart & session |
41 | +>>>>>>> MERGE-SOURCE |
42 | event-bridge. This way session logs will be rotated, even upstart is |
43 | not system init. |
44 | * debian/control: make upstart-monitor & upstart-dconf-bridge be |
45 | installable with just session init, upstart-bin. |
46 | + * extra/upstart-local-bridge: implement systemd pid1 logic. |
47 | + * extra/upstart-event-bridge: make it re-emit upstart-local-bridge |
48 | + events direct. |
49 | + * util/telinit: Revert to synchronous behaviour coupled with unavoidable |
50 | + poll to ensure telinit only returns once a re-exec has completed (LP: |
51 | + #901038). |
52 | + * move udev & local bridges to upstart-bin package. |
53 | |
54 | - -- Dimitri John Ledkov <dimitri.j.ledkov@linux.intel.com> Sun, 11 Jan 2015 01:15:34 +0000 |
55 | + -- Dimitri John Ledkov <dimitri.j.ledkov@linux.intel.com> Sat, 17 Jan 2015 01:59:42 +0000 |
56 | |
57 | upstart (1.13.2-0ubuntu5) vivid; urgency=medium |
58 | |
59 | |
60 | === modified file 'debian/control' |
61 | --- debian/control 2015-01-11 01:19:24 +0000 |
62 | +++ debian/control 2015-01-17 15:39:44 +0000 |
63 | @@ -33,8 +33,8 @@ |
64 | Architecture: any |
65 | Depends: ${shlibs:Depends}, ${misc:Depends}, sysvinit-utils, initscripts, libjson0 (>= 0.10-1.1ubuntu1), debianutils (>= 4) |
66 | Suggests: python3, graphviz, bash-completion, upstart-monitor |
67 | -Replaces: upstart (<< 1.13.2-0ubuntu3) |
68 | -Breaks: upstart (<< 1.13.2-0ubuntu3) |
69 | +Replaces: upstart (<< 1.13.2-0ubuntu6) |
70 | +Breaks: upstart (<< 1.13.2-0ubuntu6) |
71 | Multi-Arch: foreign |
72 | Description: event-based init daemon - essential binaries |
73 | upstart is a replacement for the /sbin/init daemon which handles |
74 | |
75 | === modified file 'debian/rules' |
76 | --- debian/rules 2014-11-19 11:52:17 +0000 |
77 | +++ debian/rules 2015-01-17 15:39:44 +0000 |
78 | @@ -52,7 +52,6 @@ |
79 | install -m 644 debian/upstart-bin.apport \ |
80 | debian/upstart-bin/usr/share/apport/package-hooks/source_upstart.py |
81 | rm debian/upstart-bin/usr/share/upstart/sessions/upstart-dconf-bridge.conf |
82 | - rm debian/upstart/etc/init/upstart-event-bridge.conf |
83 | rm debian/upstart/etc/init/upstart-dbus-bridge.conf |
84 | |
85 | override_dh_installcron: |
86 | |
87 | === modified file 'debian/upstart-bin.install' |
88 | --- debian/upstart-bin.install 2014-11-19 11:52:17 +0000 |
89 | +++ debian/upstart-bin.install 2015-01-17 15:39:44 +0000 |
90 | @@ -11,6 +11,8 @@ |
91 | sbin/upstart-dbus-bridge |
92 | sbin/upstart-event-bridge |
93 | sbin/upstart-file-bridge |
94 | +sbin/upstart-local-bridge |
95 | +sbin/upstart-udev-bridge |
96 | debian/running-in-container bin/ |
97 | debian/apparmor-profile-load lib/init/ |
98 | usr/share/upstart/sessions/* |
99 | @@ -31,6 +33,8 @@ |
100 | usr/share/man/man8/upstart.8 |
101 | usr/share/man/man8/upstart-file-bridge.8 |
102 | usr/share/man/man8/upstart-dbus-bridge.8 |
103 | +usr/share/man/man8/upstart-local-bridge.8 |
104 | +usr/share/man/man8/upstart-udev-bridge.8 |
105 | usr/share/man/man8/initctl2dot.8 |
106 | usr/share/man/man8/initctl.8 |
107 | usr/share/man/man5/upstart.5 |
108 | |
109 | === modified file 'debian/upstart.install' |
110 | --- debian/upstart.install 2014-11-19 11:52:17 +0000 |
111 | +++ debian/upstart.install 2015-01-17 15:39:44 +0000 |
112 | @@ -6,9 +6,7 @@ |
113 | sbin/reboot |
114 | sbin/runlevel |
115 | sbin/shutdown |
116 | -sbin/upstart-local-bridge |
117 | sbin/upstart-socket-bridge |
118 | -sbin/upstart-udev-bridge |
119 | debian/upstart-job lib/init/ |
120 | debian/migrate-inittab.pl usr/lib/upstart/ |
121 | usr/share/man/man7/control-alt-delete.7 |
122 | @@ -17,8 +15,6 @@ |
123 | usr/share/man/man7/socket-event.7 |
124 | usr/share/man/man7/power-status-changed.7 |
125 | usr/share/man/man8/shutdown.8 |
126 | -usr/share/man/man8/upstart-local-bridge.8 |
127 | -usr/share/man/man8/upstart-udev-bridge.8 |
128 | usr/share/man/man8/runlevel.8 |
129 | usr/share/man/man8/reboot.8 |
130 | usr/share/man/man8/upstart-socket-bridge.8 |
131 | |
132 | === modified file 'extra/Makefile.am' |
133 | --- extra/Makefile.am 2013-11-14 17:41:01 +0000 |
134 | +++ extra/Makefile.am 2015-01-17 15:39:44 +0000 |
135 | @@ -23,6 +23,7 @@ |
136 | conf-session/upstart-event-bridge.conf \ |
137 | conf-session/upstart-file-bridge.conf \ |
138 | conf-session/re-exec.conf \ |
139 | + conf-session/upstart-udev-bridge.conf \ |
140 | conf-session/upstart-dbus-session-bridge.conf \ |
141 | conf-session/upstart-dbus-system-bridge.conf |
142 | |
143 | @@ -33,7 +34,6 @@ |
144 | |
145 | dist_init_DATA = \ |
146 | conf/upstart-socket-bridge.conf \ |
147 | - conf/upstart-event-bridge.conf \ |
148 | conf/upstart-file-bridge.conf \ |
149 | conf/upstart-dbus-bridge.conf |
150 | |
151 | @@ -106,8 +106,9 @@ |
152 | upstart_local_bridge_SOURCES = \ |
153 | upstart-local-bridge.c |
154 | nodist_upstart_local_bridge_SOURCES = \ |
155 | + $(org_freedesktop_systemd1_OUTPUTS) \ |
156 | $(com_ubuntu_Upstart_OUTPUTS) \ |
157 | - $(com_ubuntu_Upstart_Job_OUTPUTS) |
158 | + $(control_com_ubuntu_Upstart_OUTPUTS) |
159 | upstart_local_bridge_LDADD = \ |
160 | $(LTLIBINTL) \ |
161 | $(NIH_LIBS) \ |
162 | @@ -224,15 +225,50 @@ |
163 | --output=$@ $< |
164 | |
165 | |
166 | +org_freedesktop_systemd1_OUTPUTS = \ |
167 | + org.freedesktop.systemd1.c \ |
168 | + org.freedesktop.systemd1.h |
169 | + |
170 | +org_freedesktop_systemd1_XML = \ |
171 | + org.freedesktop.systemd1.xml |
172 | + |
173 | +$(org_freedesktop_systemd1_OUTPUTS): $(org_freedesktop_systemd1_XML) |
174 | + $(AM_V_GEN)$(NIH_DBUS_TOOL) \ |
175 | + --package=$(PACKAGE) \ |
176 | + --mode=proxy --prefix=systemd \ |
177 | + --default-interface=org.freedesktop.systemd1.Manager \ |
178 | + --output=$@ $< |
179 | + |
180 | +# Server for upstart-local-bridge |
181 | +control_com_ubuntu_Upstart_OUTPUTS = \ |
182 | + control_com.ubuntu.Upstart.c \ |
183 | + control_com.ubuntu.Upstart.h |
184 | + |
185 | +control_com_ubuntu_Upstart_XML = \ |
186 | + com.ubuntu.Upstart.xml |
187 | + |
188 | +$(control_com_ubuntu_Upstart_OUTPUTS): $(control_com_ubuntu_Upstart_XML) |
189 | + $(AM_V_GEN)$(NIH_DBUS_TOOL) \ |
190 | + --package=$(PACKAGE) \ |
191 | + --mode=object --prefix=control \ |
192 | + --default-interface=com.ubuntu.Upstart0_6 \ |
193 | + --output=$@ $< |
194 | + |
195 | + |
196 | + |
197 | # These have to be built sources because we can't compile object files |
198 | # without the header file existing first |
199 | BUILT_SOURCES = \ |
200 | $(com_ubuntu_Upstart_OUTPUTS) \ |
201 | - $(com_ubuntu_Upstart_Job_OUTPUTS) |
202 | + $(control_com_ubuntu_Upstart_OUTPUTS) \ |
203 | + $(com_ubuntu_Upstart_Job_OUTPUTS) \ |
204 | + $(org_freedesktop_systemd1_OUTPUTS) |
205 | |
206 | CLEANFILES = \ |
207 | $(com_ubuntu_Upstart_OUTPUTS) \ |
208 | - $(com_ubuntu_Upstart_Job_OUTPUTS) |
209 | + $(control_com_ubuntu_Upstart_OUTPUTS) \ |
210 | + $(com_ubuntu_Upstart_Job_OUTPUTS) \ |
211 | + $(org_freedesktop_systemd1_OUTPUTS) |
212 | |
213 | |
214 | clean-local: |
215 | |
216 | === added file 'extra/com.ubuntu.Upstart.xml' |
217 | --- extra/com.ubuntu.Upstart.xml 1970-01-01 00:00:00 +0000 |
218 | +++ extra/com.ubuntu.Upstart.xml 2015-01-17 15:39:44 +0000 |
219 | @@ -0,0 +1,29 @@ |
220 | +<?xml version="1.0" encoding="UTF-8" ?> |
221 | +<!-- upstart |
222 | + |
223 | + com.ubuntu.Upstart.xml - interface definition for manager object |
224 | + |
225 | + Copyright © 2009 Canonical Ltd. |
226 | + Author: Scott James Remnant <scott@netsplit.com>. |
227 | + |
228 | + This file is free software; Canonical Ltd gives unlimited permission |
229 | + to copy and/or distribute it, with or without modifications, as long |
230 | + as this notice is preserved. |
231 | + |
232 | + Communication and interaction with Upstart through this interface is |
233 | + permitted without restriction. |
234 | + --> |
235 | + |
236 | +<!DOCTYPE node PUBLIC |
237 | + "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" |
238 | + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> |
239 | + |
240 | +<node name="/com/ubuntu/Upstart"> |
241 | + <interface name="com.ubuntu.Upstart0_6"> |
242 | + <!-- Signal for events being emitted --> |
243 | + <signal name="EventEmitted"> |
244 | + <arg name="name" type="s" /> |
245 | + <arg name="env" type="as" /> |
246 | + </signal> |
247 | + </interface> |
248 | +</node> |
249 | |
250 | === added file 'extra/conf-session/upstart-udev-bridge.conf' |
251 | --- extra/conf-session/upstart-udev-bridge.conf 1970-01-01 00:00:00 +0000 |
252 | +++ extra/conf-session/upstart-udev-bridge.conf 2015-01-17 15:39:44 +0000 |
253 | @@ -0,0 +1,22 @@ |
254 | +# upstart-udev-bridge - Bridge udev events into session upstart |
255 | +# |
256 | +# This helper daemon receives udev events from the netlink socket and |
257 | +# emits equivalent Upstart events. |
258 | + |
259 | +description "Bridge udev events into upstart" |
260 | + |
261 | +# From upstart-udev-bridge itself |
262 | +emits *-device-added |
263 | +emits *-device-removed |
264 | +emits *-device-changed |
265 | +# From http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/libudev-udev-device.html |
266 | +emits *-device-online |
267 | +emits *-device-offline |
268 | + |
269 | +start on startup |
270 | +stop on desktop-end |
271 | + |
272 | +expect daemon |
273 | +respawn |
274 | + |
275 | +exec upstart-udev-bridge --daemon --user |
276 | |
277 | === removed file 'extra/conf/upstart-event-bridge.conf' |
278 | --- extra/conf/upstart-event-bridge.conf 2013-01-22 20:08:29 +0000 |
279 | +++ extra/conf/upstart-event-bridge.conf 1970-01-01 00:00:00 +0000 |
280 | @@ -1,15 +0,0 @@ |
281 | -# upstart-event-bridge - Bridge system upstarts events into session upstart |
282 | -# |
283 | -# This helper daemon receives system upstart events from the DBus system bus |
284 | -# and emits equivalent events (with a :sys:) prefix to the session bus |
285 | - |
286 | -description "Bridge Upstart system events into session Upstart" |
287 | - |
288 | -emits :sys:* |
289 | - |
290 | -start on started dbus |
291 | -stop on stopped dbus |
292 | - |
293 | -respawn |
294 | - |
295 | -exec upstart-event-bridge |
296 | |
297 | === added file 'extra/org.freedesktop.systemd1.xml' |
298 | --- extra/org.freedesktop.systemd1.xml 1970-01-01 00:00:00 +0000 |
299 | +++ extra/org.freedesktop.systemd1.xml 2015-01-17 15:39:44 +0000 |
300 | @@ -0,0 +1,19 @@ |
301 | +<?xml version="1.0" encoding="UTF-8" ?> |
302 | +<!-- |
303 | + org.freedesktop.systemd1- interface definition for systemd manager object |
304 | + |
305 | + Public Domain |
306 | + |
307 | + Generated file using gdbus introspect call against systemd1 instance |
308 | + --> |
309 | +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" |
310 | +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> |
311 | +<node> |
312 | + <interface name="org.freedesktop.systemd1.Manager"> |
313 | + <method name="StartUnit"> |
314 | + <arg name="name" type="s" direction="in"/> |
315 | + <arg name="mode" type="s" direction="in"/> |
316 | + <arg name="job" type="o" direction="out"/> |
317 | + </method> |
318 | + </interface> |
319 | +</node> |
320 | |
321 | === modified file 'extra/upstart-event-bridge.c' |
322 | --- extra/upstart-event-bridge.c 2013-07-05 08:44:00 +0000 |
323 | +++ extra/upstart-event-bridge.c 2015-01-17 15:39:44 +0000 |
324 | @@ -26,6 +26,9 @@ |
325 | #include <stdlib.h> |
326 | #include <string.h> |
327 | #include <ctype.h> |
328 | +#include <sys/types.h> |
329 | +#include <sys/stat.h> |
330 | +#include <unistd.h> |
331 | |
332 | #include <nih/macros.h> |
333 | #include <nih/alloc.h> |
334 | @@ -42,8 +45,10 @@ |
335 | #include "dbus/upstart.h" |
336 | #include "com.ubuntu.Upstart.h" |
337 | |
338 | +#define DBUS_ADDRESS_LOCAL "unix:abstract=/com/ubuntu/upstart/local/bridge" |
339 | |
340 | /* Prototypes for static functions */ |
341 | +static int systemd_booted (void); |
342 | static void upstart_disconnected (DBusConnection *connection); |
343 | static void upstart_forward_event (void *data, NihDBusMessage *message, |
344 | const char *path); |
345 | @@ -60,6 +65,14 @@ |
346 | static int daemonise = FALSE; |
347 | |
348 | /** |
349 | + * local: |
350 | + * |
351 | + * Set to TRUE if we should connect to upstart-local-bridge instead of |
352 | + * the system init. |
353 | + **/ |
354 | +static int local = FALSE; |
355 | + |
356 | +/** |
357 | * system_upstart: |
358 | * |
359 | * Proxy to system Upstart daemon. |
360 | @@ -119,9 +132,14 @@ |
361 | exit (1); |
362 | } |
363 | |
364 | + local = systemd_booted (); |
365 | + |
366 | /* Initialise the connection to system Upstart */ |
367 | - system_connection = NIH_SHOULD (nih_dbus_bus (DBUS_BUS_SYSTEM, upstart_disconnected)); |
368 | - |
369 | + if (local) { |
370 | + system_connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_LOCAL, upstart_disconnected)); |
371 | + } else { |
372 | + system_connection = NIH_SHOULD (nih_dbus_bus (DBUS_BUS_SYSTEM, upstart_disconnected)); |
373 | + } |
374 | if (! system_connection) { |
375 | NihError *err; |
376 | |
377 | @@ -134,7 +152,7 @@ |
378 | } |
379 | |
380 | system_upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, system_connection, |
381 | - DBUS_SERVICE_UPSTART, DBUS_PATH_UPSTART, |
382 | + NULL, DBUS_PATH_UPSTART, |
383 | NULL, NULL)); |
384 | if (! system_upstart) { |
385 | NihError *err; |
386 | @@ -259,6 +277,20 @@ |
387 | return ret; |
388 | } |
389 | |
390 | +static int |
391 | +systemd_booted (void) |
392 | +{ |
393 | + struct stat st; |
394 | + |
395 | + if (lstat ("/run/systemd/system/", &st) == 0) { |
396 | + if (S_ISDIR(st.st_mode)) { |
397 | + return TRUE; |
398 | + } |
399 | + } |
400 | + |
401 | + return FALSE; |
402 | +} |
403 | + |
404 | static void |
405 | upstart_disconnected (DBusConnection *connection) |
406 | { |
407 | @@ -293,7 +325,11 @@ |
408 | nih_assert (event_name != NULL); |
409 | |
410 | /* Build the new event name */ |
411 | - NIH_MUST (nih_strcat_sprintf (&new_event_name, NULL, ":sys:%s", event_name)); |
412 | + if (local) { |
413 | + new_event_name = NIH_MUST (nih_strdup (NULL, event_name)); |
414 | + } else { |
415 | + new_event_name = NIH_MUST (nih_sprintf (NULL, ":sys:%s", event_name)); |
416 | + } |
417 | |
418 | /* Re-transmit the event */ |
419 | pending_call = upstart_emit_event (user_upstart, |
420 | |
421 | === modified file 'extra/upstart-local-bridge.c' |
422 | --- extra/upstart-local-bridge.c 2013-11-14 17:41:01 +0000 |
423 | +++ extra/upstart-local-bridge.c 2015-01-17 15:39:44 +0000 |
424 | @@ -22,10 +22,14 @@ |
425 | #endif /* HAVE_CONFIG_H */ |
426 | |
427 | #include <sys/types.h> |
428 | +#include <sys/stat.h> |
429 | #include <sys/socket.h> |
430 | #include <sys/un.h> |
431 | +#include <sys/types.h> |
432 | +#include <sys/wait.h> |
433 | |
434 | #include <errno.h> |
435 | +#include <stdio.h> |
436 | #include <stdlib.h> |
437 | #include <string.h> |
438 | #include <syslog.h> |
439 | @@ -45,24 +49,17 @@ |
440 | |
441 | #include <nih-dbus/dbus_connection.h> |
442 | #include <nih-dbus/dbus_proxy.h> |
443 | +#include <nih-dbus/dbus_object.h> |
444 | |
445 | #include "dbus/upstart.h" |
446 | #include "com.ubuntu.Upstart.h" |
447 | -#include "com.ubuntu.Upstart.Job.h" |
448 | +#include "org.freedesktop.systemd1.h" |
449 | +#include "control_com.ubuntu.Upstart.h" |
450 | |
451 | -/** |
452 | - * Job: |
453 | - * |
454 | - * @entry: list header, |
455 | - * @path: D-Bus path for a job. |
456 | - * |
457 | - * Representation of an Upstart Job. |
458 | - * |
459 | - **/ |
460 | -typedef struct job { |
461 | - NihList entry; |
462 | - char *path; |
463 | -} Job; |
464 | +#define DBUS_ADDRESS_SYSTEMD "unix:path=/run/systemd/private" |
465 | +#define DBUS_PATH_SYSTEMD "/org/freedesktop/systemd1" |
466 | +#define DBUS_SERVICE_SYSTEMD "org.freedesktop.systemd1" |
467 | +#define DBUS_ADDRESS_LOCAL "unix:abstract=/com/ubuntu/upstart/local/bridge" |
468 | |
469 | /** |
470 | * Socket: |
471 | @@ -100,12 +97,14 @@ |
472 | struct ucred ucred; |
473 | } ClientConnection; |
474 | |
475 | -static void upstart_job_added (void *data, NihDBusMessage *message, |
476 | - const char *job); |
477 | -static void upstart_job_removed (void *data, NihDBusMessage *message, |
478 | - const char *job); |
479 | static void upstart_connect (void); |
480 | -static void upstart_disconnected (DBusConnection *connection); |
481 | +static void systemd_connect (void); |
482 | +static int systemd_booted (void); |
483 | +static int control_server_open (void); |
484 | +static int control_server_connect (DBusServer *server, |
485 | + DBusConnection *conn); |
486 | +static void control_disconnected (DBusConnection *conn); |
487 | +static void init_disconnected (DBusConnection *connection); |
488 | |
489 | static Socket *create_socket (void *parent); |
490 | |
491 | @@ -121,6 +120,8 @@ |
492 | |
493 | static void emit_event (ClientConnection *client, const char *pair, size_t len); |
494 | |
495 | +static void process_event (ClientConnection *client, const char *pair, size_t len); |
496 | + |
497 | static void signal_handler (void *data, NihSignal *signal); |
498 | |
499 | static void cleanup (void); |
500 | @@ -134,13 +135,6 @@ |
501 | static int daemonise = FALSE; |
502 | |
503 | /** |
504 | - * jobs: |
505 | - * |
506 | - * Jobs that we're monitoring. |
507 | - **/ |
508 | -static NihHash *jobs = NULL; |
509 | - |
510 | -/** |
511 | * upstart: |
512 | * |
513 | * Proxy to Upstart daemon. |
514 | @@ -148,9 +142,32 @@ |
515 | static NihDBusProxy *upstart = NULL; |
516 | |
517 | /** |
518 | + * systemd: |
519 | + * |
520 | + * Proxy to systemd daemon. |
521 | + **/ |
522 | +static NihDBusProxy *systemd = NULL; |
523 | + |
524 | +/** |
525 | + * control_server |
526 | + * |
527 | + * D-Bus server listening for new direct connections. |
528 | + **/ |
529 | +DBusServer *control_server = NULL; |
530 | + |
531 | +/** |
532 | + * control_conns: |
533 | + * |
534 | + * Open control connections, including the connection to a D-Bus |
535 | + * bus and any private client connections. |
536 | + **/ |
537 | +NihList *control_conns = NULL; |
538 | + |
539 | +/** |
540 | * event_name: |
541 | * |
542 | - * Name of event this bridge emits. |
543 | + * upstart: Name of event this bridge emits. |
544 | + * systmed: Name of target this generator creates. |
545 | **/ |
546 | static char *event_name = NULL; |
547 | |
548 | @@ -202,7 +219,7 @@ |
549 | { 0, "daemon", N_("Detach and run in the background"), |
550 | NULL, NULL, &daemonise, NULL }, |
551 | |
552 | - { 0, "event", N_("specify name of event to emit on receipt of name=value pair"), |
553 | + { 0, "event", N_("specify name of event to emit / target to generate on receipt of name=value pair"), |
554 | NULL, "EVENT", &event_name, NULL }, |
555 | |
556 | { 0, "any-user", N_("allow any user to connect"), |
557 | @@ -258,7 +275,7 @@ |
558 | |
559 | nih_main_init (argv[0]); |
560 | |
561 | - nih_option_set_synopsis (_("Local socket Upstart Bridge")); |
562 | + nih_option_set_synopsis (_("Local socket Upstart Bridge & systemd generator")); |
563 | nih_option_set_help ( |
564 | _("By default, this bridge does not detach from the " |
565 | "console and remains in the foreground. Use the --daemon " |
566 | @@ -273,9 +290,6 @@ |
567 | exit (1); |
568 | } |
569 | |
570 | - /* Allocate jobs hash table */ |
571 | - jobs = NIH_MUST (nih_hash_string_new (NULL, 0)); |
572 | - |
573 | sock = create_socket (NULL); |
574 | if (! sock) { |
575 | nih_fatal ("%s %s", |
576 | @@ -286,7 +300,26 @@ |
577 | |
578 | nih_debug ("Connected to socket '%s' on fd %d", socket_name, sock->sock); |
579 | |
580 | - upstart_connect (); |
581 | + if (systemd_booted() == TRUE) { |
582 | + systemd_connect (); |
583 | + } else { |
584 | + upstart_connect (); |
585 | + } |
586 | + |
587 | + control_conns = NIH_MUST (nih_list_new (NULL)); |
588 | + |
589 | + while ((ret = control_server_open ()) < 0) { |
590 | + NihError *err; |
591 | + |
592 | + err = nih_error_get (); |
593 | + if (err->number != ENOMEM) { |
594 | + nih_warn ("%s: %s", _("Unable to listen for private" |
595 | + "connections"), err->message); |
596 | + nih_free (err); |
597 | + break; |
598 | + } |
599 | + nih_free (err); |
600 | + } |
601 | |
602 | /* Become daemon */ |
603 | if (daemonise) { |
604 | @@ -326,103 +359,14 @@ |
605 | return ret; |
606 | } |
607 | |
608 | -static void |
609 | -upstart_job_added (void *data, |
610 | - NihDBusMessage *message, |
611 | - const char *job_class_path) |
612 | -{ |
613 | - nih_local NihDBusProxy *job_class = NULL; |
614 | - nih_local char ***start_on = NULL; |
615 | - nih_local char ***stop_on = NULL; |
616 | - Job *job; |
617 | - |
618 | - nih_assert (job_class_path != NULL); |
619 | - |
620 | - /* Obtain a proxy to the job */ |
621 | - job_class = nih_dbus_proxy_new (NULL, upstart->connection, |
622 | - upstart->name, job_class_path, |
623 | - NULL, NULL); |
624 | - if (! job_class) { |
625 | - NihError *err; |
626 | - |
627 | - err = nih_error_get (); |
628 | - nih_error ("Could not create proxy for job %s: %s", |
629 | - job_class_path, err->message); |
630 | - nih_free (err); |
631 | - |
632 | - return; |
633 | - } |
634 | - |
635 | - job_class->auto_start = FALSE; |
636 | - |
637 | - /* Obtain the start_on and stop_on properties of the job */ |
638 | - if (job_class_get_start_on_sync (NULL, job_class, &start_on) < 0) { |
639 | - NihError *err; |
640 | - |
641 | - err = nih_error_get (); |
642 | - nih_error ("Could not obtain job start condition %s: %s", |
643 | - job_class_path, err->message); |
644 | - nih_free (err); |
645 | - |
646 | - return; |
647 | - } |
648 | - |
649 | - if (job_class_get_stop_on_sync (NULL, job_class, &stop_on) < 0) { |
650 | - NihError *err; |
651 | - |
652 | - err = nih_error_get (); |
653 | - nih_error ("Could not obtain job stop condition %s: %s", |
654 | - job_class_path, err->message); |
655 | - nih_free (err); |
656 | - |
657 | - return; |
658 | - } |
659 | - |
660 | - /* Free any existing record for the job (should never happen, |
661 | - * but worth being safe). |
662 | - */ |
663 | - job = (Job *)nih_hash_lookup (jobs, job_class_path); |
664 | - if (job) |
665 | - nih_free (job); |
666 | - |
667 | - /* Create new record for the job */ |
668 | - job = NIH_MUST (nih_new (NULL, Job)); |
669 | - job->path = NIH_MUST (nih_strdup (job, job_class_path)); |
670 | - |
671 | - nih_list_init (&job->entry); |
672 | - |
673 | - nih_debug ("Job got added %s", job_class_path); |
674 | - |
675 | - nih_alloc_set_destructor (job, nih_list_destroy); |
676 | - |
677 | - /* Add all jobs */ |
678 | - nih_hash_add (jobs, &job->entry); |
679 | -} |
680 | - |
681 | -static void |
682 | -upstart_job_removed (void *data, |
683 | - NihDBusMessage *message, |
684 | - const char *job_path) |
685 | -{ |
686 | - Job *job; |
687 | - |
688 | - nih_assert (job_path != NULL); |
689 | - |
690 | - job = (Job *)nih_hash_lookup (jobs, job_path); |
691 | - if (job) { |
692 | - nih_debug ("Job went away %s", job_path); |
693 | - nih_free (job); |
694 | - } |
695 | -} |
696 | |
697 | static void |
698 | upstart_connect (void) |
699 | { |
700 | DBusConnection *connection; |
701 | - char **job_class_paths; |
702 | |
703 | /* Initialise the connection to Upstart */ |
704 | - connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected)); |
705 | + connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, init_disconnected)); |
706 | if (! connection) { |
707 | NihError *err; |
708 | |
709 | @@ -449,59 +393,169 @@ |
710 | } |
711 | |
712 | nih_debug ("Connected to Upstart"); |
713 | - |
714 | - /* Connect signals to be notified when jobs come and go */ |
715 | - if (! nih_dbus_proxy_connect (upstart, &upstart_com_ubuntu_Upstart0_6, "JobAdded", |
716 | - (NihDBusSignalHandler)upstart_job_added, NULL)) { |
717 | - NihError *err; |
718 | - |
719 | - err = nih_error_get (); |
720 | - nih_fatal ("%s: %s", _("Could not create JobAdded signal connection"), |
721 | - err->message); |
722 | - nih_free (err); |
723 | - |
724 | - exit (1); |
725 | - } |
726 | - |
727 | - if (! nih_dbus_proxy_connect (upstart, &upstart_com_ubuntu_Upstart0_6, "JobRemoved", |
728 | - (NihDBusSignalHandler)upstart_job_removed, NULL)) { |
729 | - NihError *err; |
730 | - |
731 | - err = nih_error_get (); |
732 | - nih_fatal ("%s: %s", _("Could not create JobRemoved signal connection"), |
733 | - err->message); |
734 | - nih_free (err); |
735 | - |
736 | - exit (1); |
737 | - } |
738 | - |
739 | - /* Request a list of all current jobs */ |
740 | - if (upstart_get_all_jobs_sync (NULL, upstart, &job_class_paths) < 0) { |
741 | - NihError *err; |
742 | - |
743 | - err = nih_error_get (); |
744 | - nih_fatal ("%s: %s", _("Could not obtain job list"), |
745 | - err->message); |
746 | - nih_free (err); |
747 | - |
748 | - exit (1); |
749 | - } |
750 | - |
751 | - for (char **job_class_path = job_class_paths; |
752 | - job_class_path && *job_class_path; job_class_path++) |
753 | - upstart_job_added (NULL, NULL, *job_class_path); |
754 | - |
755 | - nih_free (job_class_paths); |
756 | -} |
757 | - |
758 | -static void |
759 | -upstart_disconnected (DBusConnection *connection) |
760 | -{ |
761 | - nih_fatal (_("Disconnected from Upstart")); |
762 | +} |
763 | + |
764 | +static void |
765 | +systemd_connect (void) |
766 | +{ |
767 | + DBusConnection *connection; |
768 | + |
769 | + /* Initialise the connection to systemd */ |
770 | + /* /run/systemd/private is supposedly "private" end-point |
771 | + * which systemctl & libsystemd use */ |
772 | + connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_SYSTEMD, init_disconnected)); |
773 | + if (! connection) { |
774 | + NihError *err; |
775 | + |
776 | + err = nih_error_get (); |
777 | + nih_fatal ("%s: %s", _("Could not connect to systemd"), |
778 | + err->message); |
779 | + nih_free (err); |
780 | + |
781 | + exit (1); |
782 | + } |
783 | + |
784 | + systemd = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection, |
785 | + NULL, DBUS_PATH_SYSTEMD, |
786 | + NULL, NULL)); |
787 | + if (! systemd) { |
788 | + NihError *err; |
789 | + |
790 | + err = nih_error_get (); |
791 | + nih_fatal ("%s: %s", _("Could not create systemd proxy"), |
792 | + err->message); |
793 | + nih_free (err); |
794 | + |
795 | + exit (1); |
796 | + } |
797 | + |
798 | + FILE *fp = NULL; |
799 | + nih_local char *template_name = NULL; |
800 | + |
801 | + template_name = NIH_MUST (nih_sprintf (NULL, "/run/systemd/system/%s@.target", event_name)); |
802 | + |
803 | + fp = NIH_SHOULD (fopen(template_name, "we")); |
804 | + if (!fp) { |
805 | + nih_fatal ("%s %s", _("Failed to create target template"), |
806 | + strerror (errno)); |
807 | + exit (1); |
808 | + } |
809 | + fprintf (fp, |
810 | + "# Automatically generated by %s\n\n" |
811 | + "[Unit]\n" |
812 | + "Description=Local bridge key value pairs\n" |
813 | + "Documentation=man:%s\n", |
814 | + program_name, program_name); |
815 | + fflush (fp); |
816 | + if (ferror (fp)) { |
817 | + nih_fatal ("%s %s", _("Failed to write target template"), |
818 | + strerror (errno)); |
819 | + exit (1); |
820 | + } |
821 | + fclose (fp); |
822 | + |
823 | + nih_debug ("Connected to systemd"); |
824 | +} |
825 | + |
826 | +static int |
827 | +systemd_booted (void) |
828 | +{ |
829 | + struct stat st; |
830 | + |
831 | + if (lstat ("/run/systemd/system/", &st) == 0) { |
832 | + if (S_ISDIR(st.st_mode)) { |
833 | + return TRUE; |
834 | + } |
835 | + } |
836 | + |
837 | + return FALSE; |
838 | +} |
839 | + |
840 | +static void |
841 | +init_disconnected (DBusConnection *connection) |
842 | +{ |
843 | + nih_fatal (_("Disconnected from init")); |
844 | nih_main_loop_exit (1); |
845 | } |
846 | |
847 | /** |
848 | + * control_server_open: |
849 | + * |
850 | + * Open a listening D-Bus server and store it in the control_server global. |
851 | + * New connections are permitted from the root user, and handled |
852 | + * automatically in the main loop. |
853 | + * |
854 | + * Returns: zero on success, negative value on raised error. |
855 | + **/ |
856 | + |
857 | +int |
858 | +control_server_open (void) |
859 | +{ |
860 | + nih_assert (control_server == NULL); |
861 | + |
862 | + control_server = nih_dbus_server (DBUS_ADDRESS_LOCAL, |
863 | + control_server_connect, |
864 | + control_disconnected); |
865 | + if (! control_server) |
866 | + return -1; |
867 | + |
868 | + nih_debug("D-Bus server started at address: %s", DBUS_ADDRESS_LOCAL); |
869 | + |
870 | + return 0; |
871 | +} |
872 | + |
873 | +/** |
874 | + * control_server_connect: |
875 | + * |
876 | + * Called when a new client connects to our server and is used to register |
877 | + * objects on the new connection. |
878 | + * |
879 | + * Returns: always TRUE. |
880 | + **/ |
881 | +static int |
882 | +control_server_connect (DBusServer *server, |
883 | + DBusConnection *conn) |
884 | +{ |
885 | + nih_assert (server != NULL); |
886 | + nih_assert (server == control_server); |
887 | + nih_assert (conn != NULL); |
888 | + NihListEntry *entry = NULL; |
889 | + |
890 | + /* Register objects on the connection. */ |
891 | + NIH_MUST (nih_dbus_object_new (NULL, conn, DBUS_PATH_UPSTART, |
892 | + control_interfaces, NULL)); |
893 | + |
894 | + |
895 | + entry = NIH_MUST (nih_list_entry_new (NULL)); |
896 | + entry->data = conn; |
897 | + nih_list_add (control_conns, &entry->entry); |
898 | + nih_debug("Connection from private client"); |
899 | + |
900 | + return TRUE; |
901 | +} |
902 | + |
903 | +/** |
904 | + * control_disconnected: |
905 | + * |
906 | + * This function is called when the connection to the D-Bus system bus, |
907 | + * or a client connection to our D-Bus server, is dropped and our reference |
908 | + * is about to be list. We clear the connection from our current list |
909 | + * and drop the control_bus global if relevant. |
910 | + **/ |
911 | +static void |
912 | +control_disconnected (DBusConnection *conn) |
913 | +{ |
914 | + nih_assert (conn != NULL); |
915 | + /* Remove from the connections list */ |
916 | + NIH_LIST_FOREACH_SAFE (control_conns, iter) { |
917 | + NihListEntry *entry = (NihListEntry *)iter; |
918 | + |
919 | + if (entry->data == conn) |
920 | + nih_free (entry); |
921 | + } |
922 | +} |
923 | + |
924 | +/** |
925 | * socket_watcher: |
926 | * |
927 | * @sock: Socket, |
928 | @@ -645,7 +699,7 @@ |
929 | if (used_len < min_len) |
930 | continue; |
931 | |
932 | - emit_event (client, pair, used_len); |
933 | + process_event (client, pair, used_len); |
934 | } |
935 | |
936 | /* Consume the entire length */ |
937 | @@ -724,6 +778,8 @@ |
938 | /* Handle abstract names */ |
939 | if (sock->sun_addr.sun_path[0] == '@') |
940 | sock->sun_addr.sun_path[0] = '\0'; |
941 | + else |
942 | + (void) unlink(sock->sun_addr.sun_path); |
943 | |
944 | sock->sock = socket (sock->addr.sa_family, SOCK_STREAM, 0); |
945 | if (sock->sock < 0) { |
946 | @@ -830,17 +886,102 @@ |
947 | /* Add the name=value pair */ |
948 | NIH_MUST (nih_str_array_addn (&env, NULL, NULL, pair, len)); |
949 | |
950 | - pending_call = upstart_emit_event (upstart, |
951 | - event_name, env, FALSE, |
952 | - NULL, emit_event_error, NULL, |
953 | - NIH_DBUS_TIMEOUT_NEVER); |
954 | - |
955 | - if (! pending_call) { |
956 | + if (upstart) { |
957 | + pending_call = upstart_emit_event (upstart, |
958 | + event_name, env, FALSE, |
959 | + NULL, emit_event_error, NULL, |
960 | + NIH_DBUS_TIMEOUT_NEVER); |
961 | + |
962 | + if (! pending_call) { |
963 | + NihError *err; |
964 | + err = nih_error_get (); |
965 | + nih_warn ("%s", err->message); |
966 | + nih_free (err); |
967 | + } |
968 | + |
969 | + dbus_pending_call_unref (pending_call); |
970 | + } |
971 | + |
972 | + NIH_LIST_FOREACH (control_conns, iter) { |
973 | + NihListEntry *entry = (NihListEntry *)iter; |
974 | + DBusConnection *conn = (DBusConnection *)entry->data; |
975 | + |
976 | + NIH_ZERO (control_emit_event_emitted (conn, DBUS_PATH_UPSTART, |
977 | + event_name, env)); |
978 | + } |
979 | + |
980 | +} |
981 | + |
982 | +static void |
983 | +systemd_launch_instance (ClientConnection *client, |
984 | + const char *pair, |
985 | + size_t len) |
986 | +{ |
987 | + nih_local char *safe_pair = NULL; |
988 | + nih_local char **key_value = NULL; |
989 | + nih_local char *group_name = NULL; |
990 | + nih_local char *unit_name = NULL; |
991 | + nih_local char *job_name = NULL; |
992 | + |
993 | + nih_assert (client); |
994 | + nih_assert (pair); |
995 | + nih_assert (len); |
996 | + |
997 | + /* Why is pair not null-terminated?! */ |
998 | + safe_pair = NIH_MUST (nih_strndup (NULL, pair, len)); |
999 | + |
1000 | + /* Get key val from the key=val pair */ |
1001 | + key_value = NIH_MUST (nih_str_split (NULL, safe_pair, "=", TRUE)); |
1002 | + |
1003 | + /* Construct systemd event@key=*.target group name */ |
1004 | + group_name = NIH_MUST (nih_sprintf (NULL, "%s@%s=*.target", |
1005 | + event_name, key_value[0])); |
1006 | + |
1007 | + /* Construct systemd event@key=value.target unit name */ |
1008 | + unit_name = NIH_MUST (nih_sprintf (NULL, "%s@%s\\x3d%s.target", |
1009 | + event_name, key_value[0], |
1010 | + key_value[1])); |
1011 | + |
1012 | + /* Stop group */ |
1013 | + int pid = -1; |
1014 | + siginfo_t info; |
1015 | + do { |
1016 | + pid = fork (); |
1017 | + } while (pid < 0); |
1018 | + |
1019 | + if (pid) { |
1020 | + info.si_code = 0; |
1021 | + info.si_status = 0; |
1022 | + if (waitid (P_PID, pid, &info, WEXITED)) { |
1023 | + nih_fatal ("%s %s", _("Failed to wait for systemctl"), |
1024 | + strerror (errno)); |
1025 | + } |
1026 | + if (info.si_code != CLD_EXITED || info.si_status) { |
1027 | + nih_fatal ("Bad systemctl exit code %i and status %i\n", info.si_code, info.si_status); |
1028 | + } |
1029 | + } else { |
1030 | + /* Create and submit stop state transition, do not wait to complete */ |
1031 | + execlp ("systemctl", "systemctl", "--no-block", "stop", group_name, (char *)NULL); |
1032 | + } |
1033 | + |
1034 | + /* Create and submit start state transition, do not wait to complete */ |
1035 | + if (systemd_start_unit_sync (NULL, systemd, unit_name, "replace", &job_name)) { |
1036 | NihError *err; |
1037 | err = nih_error_get (); |
1038 | nih_warn ("%s", err->message); |
1039 | nih_free (err); |
1040 | } |
1041 | - |
1042 | - dbus_pending_call_unref (pending_call); |
1043 | +} |
1044 | + |
1045 | + |
1046 | +static void |
1047 | +process_event (ClientConnection *client, |
1048 | + const char *pair, |
1049 | + size_t len) |
1050 | +{ |
1051 | + emit_event (client, pair, len); |
1052 | + |
1053 | + if (systemd) { |
1054 | + systemd_launch_instance (client, pair, len); |
1055 | + } |
1056 | } |
1057 | |
1058 | === modified file 'extra/upstart-udev-bridge.c' |
1059 | --- extra/upstart-udev-bridge.c 2013-10-18 15:02:34 +0000 |
1060 | +++ extra/upstart-udev-bridge.c 2015-01-17 15:39:44 +0000 |
1061 | @@ -69,6 +69,15 @@ |
1062 | static NihDBusProxy *upstart = NULL; |
1063 | |
1064 | /** |
1065 | + * user: |
1066 | + * |
1067 | + * If TRUE, run in User Session mode connecting to the Session Init |
1068 | + * rather than PID 1. In this mode, certain relative paths are also |
1069 | + * expanded. |
1070 | + **/ |
1071 | +static int user = FALSE; |
1072 | + |
1073 | +/** |
1074 | * no_strip_udev_data: |
1075 | * |
1076 | * If TRUE, do not modify any udev message data (old behaviour). |
1077 | @@ -86,6 +95,8 @@ |
1078 | NULL, NULL, &daemonise, NULL }, |
1079 | { 0, "no-strip", N_("Do not strip non-printable bytes from udev message data"), |
1080 | NULL, NULL, &no_strip_udev_data, NULL }, |
1081 | + { 0, "user", N_("Connect to user session"), |
1082 | + NULL, NULL, &user, NULL }, |
1083 | |
1084 | NIH_OPTION_LAST |
1085 | }; |
1086 | @@ -97,6 +108,11 @@ |
1087 | { |
1088 | char ** args; |
1089 | DBusConnection * connection; |
1090 | + char * pidfile_path = NULL; |
1091 | + char * pidfile = NULL; |
1092 | + char *user_session_addr = NULL; |
1093 | + nih_local char ** user_session_path = NULL; |
1094 | + char * path_element = NULL; |
1095 | struct udev * udev; |
1096 | struct udev_monitor *udev_monitor; |
1097 | int ret; |
1098 | @@ -113,8 +129,19 @@ |
1099 | if (! args) |
1100 | exit (1); |
1101 | |
1102 | + if (user) { |
1103 | + user_session_addr = getenv ("UPSTART_SESSION"); |
1104 | + if (! user_session_addr) { |
1105 | + nih_fatal (_("UPSTART_SESSION isn't set in environment")); |
1106 | + exit (EXIT_FAILURE); |
1107 | + } |
1108 | + } |
1109 | + |
1110 | /* Initialise the connection to Upstart */ |
1111 | - connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected)); |
1112 | + connection = NIH_SHOULD (nih_dbus_connect (user |
1113 | + ? user_session_addr |
1114 | + : DBUS_ADDRESS_UPSTART, |
1115 | + upstart_disconnected)); |
1116 | if (! connection) { |
1117 | NihError *err; |
1118 | |
1119 | @@ -153,6 +180,35 @@ |
1120 | |
1121 | /* Become daemon */ |
1122 | if (daemonise) { |
1123 | + /* Deal with the pidfile location when becoming a daemon. |
1124 | + * We need to be able to run one bridge per upstart daemon. |
1125 | + * Store the PID file in XDG_RUNTIME_DIR or HOME and include the pid of |
1126 | + * the Upstart instance (last part of the DBus path) in the filename. |
1127 | + */ |
1128 | + |
1129 | + if (user) { |
1130 | + /* Extract PID from UPSTART_SESSION */ |
1131 | + user_session_path = nih_str_split (NULL, user_session_addr, "/", TRUE); |
1132 | + |
1133 | + for (int i = 0; user_session_path && user_session_path[i]; i++) |
1134 | + path_element = user_session_path[i]; |
1135 | + |
1136 | + if (! path_element) { |
1137 | + nih_fatal (_("Invalid value for UPSTART_SESSION")); |
1138 | + exit (1); |
1139 | + } |
1140 | + |
1141 | + pidfile_path = getenv ("XDG_RUNTIME_DIR"); |
1142 | + if (!pidfile_path) |
1143 | + pidfile_path = getenv ("HOME"); |
1144 | + |
1145 | + if (pidfile_path) { |
1146 | + NIH_MUST (nih_strcat_sprintf (&pidfile, NULL, "%s/%s.%s.pid", |
1147 | + pidfile_path, program_invocation_short_name, path_element)); |
1148 | + nih_main_set_pidfile (pidfile); |
1149 | + } |
1150 | + } |
1151 | + |
1152 | if (nih_main_daemonise () < 0) { |
1153 | NihError *err; |
1154 | |
1155 | @@ -163,10 +219,12 @@ |
1156 | |
1157 | exit (1); |
1158 | } |
1159 | - |
1160 | - /* Send all logging output to syslog */ |
1161 | - openlog (program_name, LOG_PID, LOG_DAEMON); |
1162 | - nih_log_set_logger (nih_logger_syslog); |
1163 | + |
1164 | + if (!user) { |
1165 | + /* Send all logging output to syslog for system bridge */ |
1166 | + openlog (program_name, LOG_PID, LOG_DAEMON); |
1167 | + nih_log_set_logger (nih_logger_syslog); |
1168 | + } |
1169 | } |
1170 | |
1171 | /* Handle TERM and INT signals gracefully */ |
1172 | |
1173 | === modified file 'util/telinit.c' |
1174 | --- util/telinit.c 2014-03-10 13:43:50 +0000 |
1175 | +++ util/telinit.c 2015-01-17 15:39:44 +0000 |
1176 | @@ -160,27 +160,73 @@ |
1177 | int |
1178 | restart_upstart (void) |
1179 | { |
1180 | - nih_local NihDBusProxy *upstart = NULL; |
1181 | - DBusPendingCall *ret; |
1182 | + nih_local NihDBusProxy *upstart = NULL; |
1183 | + NihError *err; |
1184 | + int ret; |
1185 | |
1186 | upstart = upstart_open (NULL); |
1187 | if (! upstart) |
1188 | return -1; |
1189 | |
1190 | - /* Fire and forget: |
1191 | - * |
1192 | - * Ask Upstart to restart itself using the async interface to |
1193 | - * avoid the client-side complaining if and when it detects that |
1194 | - * Upstart has severed all connections to perform the re-exec. |
1195 | - */ |
1196 | - ret = upstart_restart (upstart, NULL, NULL, NULL, 0); |
1197 | - dbus_connection_flush(upstart->connection); |
1198 | - |
1199 | - /* We don't care about the return code, but we have to keep |
1200 | - * the compiler happy. |
1201 | - */ |
1202 | - if (ret != (DBusPendingCall *)TRUE) |
1203 | - return 0; |
1204 | + /* Ask Upstart to restart itself. |
1205 | + * |
1206 | + * Since it is not possible to serialise a D-Bus connection, |
1207 | + * Upstart is forced to sever all D-Bus client connections, |
1208 | + * including this one. |
1209 | + * |
1210 | + * Further, since the user expects telinit to block _until the |
1211 | + * re-exec has finished and Upstart is accepting connections |
1212 | + * once again_, the only solution is to wait for the forced |
1213 | + * disconnect, then poll until it is possible to create a new |
1214 | + * connection. |
1215 | + * |
1216 | + * Note that we don't (can't) care about the return code since |
1217 | + * it's not reliable: |
1218 | + * |
1219 | + * - either the re-exec request completed and D-Bus returned zero |
1220 | + * before Upstart started the re-exec. |
1221 | + * |
1222 | + * - or the re-exec request completed but upstart started the |
1223 | + * re-exec (severing all D-Bus connections) before D-Bus got a |
1224 | + * chance to finish cleanly meaning we receive a return of -1. |
1225 | + * |
1226 | + * We cannot know exactly what happened so have to allow for |
1227 | + * both scenarios. Note the implicit assumption that the re-exec |
1228 | + * request itself was accepted. If this assumption is incorrect |
1229 | + * (should not be possible), the worst case scenario is that |
1230 | + * upstart does not re-exec and then we quickly drop out of the |
1231 | + * reconnect block since it never went offline. |
1232 | + */ |
1233 | + ret = upstart_restart_sync (NULL, upstart); |
1234 | + |
1235 | + if (ret < 0) { |
1236 | + err = nih_error_get (); |
1237 | + nih_free (err); |
1238 | + } |
1239 | + |
1240 | + nih_free (upstart); |
1241 | + |
1242 | + nih_debug ("Waiting for upstart to finish re-exec"); |
1243 | + |
1244 | + /* We believe Upstart is now in the process of |
1245 | + * re-exec'ing so attempt forever to reconnect. |
1246 | + * |
1247 | + * This sounds dangerous but there is no other option, |
1248 | + * and a connection must be possible unless the system |
1249 | + * is completely broken. |
1250 | + */ |
1251 | + while (TRUE) { |
1252 | + |
1253 | + upstart = upstart_open (NULL); |
1254 | + if (upstart) |
1255 | + break; |
1256 | + |
1257 | + err = nih_error_get (); |
1258 | + nih_free (err); |
1259 | + |
1260 | + /* Avoid DoS'ing the system whilst we wait */ |
1261 | + usleep (100000); |
1262 | + } |
1263 | |
1264 | return 0; |
1265 | } |
This merge proposal is in SILO 01