Merge lp:~xnox/upstart/systemd-local-bridge into lp:ubuntu/vivid/upstart
- systemd-local-bridge
- Merge into vivid
Proposed by
Dimitri John Ledkov
on 2015-01-16
| 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 | 2015-01-19 | Pending | |
| Ubuntu branches | 2015-01-16 | Pending | |
|
Review via email:
|
|||
Commit Message
Description of the Change
To post a comment you must log in.
lp:~xnox/upstart/systemd-local-bridge
updated
on 2015-01-17
- 1599. By Dimitri John Ledkov on 2015-01-16
-
* 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 on 2015-01-17
-
Add control xml bindings.
- 1601. By Dimitri John Ledkov on 2015-01-17
-
Drop event-bridge
- 1602. By Dimitri John Ledkov on 2015-01-17
-
move udev & local bridges to upstart-bin package.
- 1603. By Dimitri John Ledkov on 2015-01-17
-
Drop local option, use systemd_booted detection instead.
- 1604. By Dimitri John Ledkov on 2015-01-17
-
releasing package upstart version 1.13.2-0ubuntu6
- 1605. By Dimitri John Ledkov on 2015-01-17
-
Correct upstart-udev-bridge session job start/stop on conditions.
| 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