This commit works around systemd -> dbus -> (nss) -> systemd deadlock
occuring in Tizen.
Situation is depicted on diagram below:
systemd dbus nss
| . .
| . .
1> reads config . .
| . .
2> reg. nofification . .
| for dbus.service . .
| . .
| . .
3> exec. services . .
| | . .
| (start srv...) . .
| | . .
| 4>------------(exec) .
| | .
*-<---(notification)=<| .
\ | .
.\> call dbus.serv | .
. handler | .
. | 4a> read config .
. |> conn. to bus | .
. | 4b> resolve user .
. |> call dbus . and groups .
. \ . initgroups() .
. ------------>. | .
. (blocking) . \---------->select module
. . (blocking) based on conf.
. . |
(below not executed) . |> security-manager
. . | module selected
. . |
. . |
[sec-manager.socket]<---------------------<| call security-manager
. . (DEADLOCK) . on unix socket
. . .
Solid line (|) means active thread of execution, dot (.) means
code not executed (blocked).
The root cause of the problem is that systemd calls external
API in blocking manner, which, due to system configuration, requires
systemd to handle its request for successful completion.
(systemd should start security-manager service via sec-manager.socket
activation).
The exact place this situation is triggered is in dbus' initialization.
This commits works around this problem by delaying dbus.service readyness
notification - effectively - resolving the problem.
Situation becomes:
systemd dbus nss security-manager
| . . .
| . . .
1> reads config . . .
| . . .
2> reg. nofification . . .
| for dbus.service . . .
| . . .
| . . .
3> exec. services . . .
| | . . .
| (start srv...) . . .
| | . . .
| 4>------------(exec) . .
| | . .
| | . .
| | . .
| | . .
| | . .
| 4a> read config . .
| | . .
| 4b> resolve user . .
| . and groups . .
| . initgroups() . .
| . | . .
| . \---------->select module .
| . (blocking) based on conf. .
| . | .
| . |> security-manager .
| . | module selected .
| . | .
| . | .
[sec-manager.socket]<---------------------<| call security-manager .
. | . . on unix socket .
. | . .
. |> exec service ----------------------------------------------->(exec)
. | . . |
<--| . |<-------------------------<| handle call
| . | |
| |<-----------------| |
| | . |
| | . |
.\> call dbus.serv |>finish conf. file. |
. handler | parsing . |
. | | . |
*-<---(notification)-<|> explicitly . |
.\ | | notify startup . |
. \> call dbus.serv | finished . |
| handler | . |
. | | . |
. |> conn. to bus | . |
. | | . |
. |> call dbus | . |
. \ | . |
. ------------>* dispatch loop . |
. (blocking) | . |
. | . |
|<--------------------< handle call . |
| | . |
Change-Id: Ifeaf299fc8653b583cd06ca9fd4f9f8045a2bde0
Requires=dbus.socket
[Service]
+Type=notify
ExecStart=@EXPANDED_BINDIR@/dbus-daemon --system --address=systemd: --nofork --systemd-activation
ExecReload=@EXPANDED_BINDIR@/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
OOMScoreAdjust=-900
#include "apparmor.h"
#include "audit.h"
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
static BusContext *context;
#ifdef DBUS_UNIX
dbus_set_protocol_version (DBUS_MAJOR_PROTOCOL_VERSION);
+#ifdef HAVE_SYSTEMD
+ sd_notify(0, "READY=1");
+#endif
+
_dbus_verbose ("We are on D-Bus...\n");
_dbus_loop_run (bus_context_get_loop (context));