From d3137dbb3789392cd306a540b7c3559128dd033e Mon Sep 17 00:00:00 2001 From: Chengwei Yang Date: Tue, 15 Oct 2013 13:27:51 +0800 Subject: [PATCH v4 2/3] Handle activated child stdout/stderr correctly in systemd environment In systemd environment, dbus-daemon will run as no-fork mode since this is the recommended practice of systemd. In that scenario, child activated by dbus-daemon will inherit dbus-daemon standard streams, includes stdin/stdout/stderr. stdin will be redirected to /dev/null by systemd and stdout/stderr will be catched by systemd log subsystem. Since the child inherit stdout/stderr from dbus-daemon, so from systemd journal log, the child log output will be identified with dbus-daemon identifier. So it's a little confusing. This patch redirects the child stdout/stderr to systemd journal stream, and with its owned service name as identifier. However, thing not fixed perfectly due to the socket ucred of the child is owned by dbus-daemon, so the pid isn't the real pid of the chile. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68559 --- configure.ac | 2 +- dbus/dbus-spawn.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b29c8f0..37e555b 100644 --- a/configure.ac +++ b/configure.ac @@ -1143,7 +1143,7 @@ if test x$enable_systemd = xno ; then have_systemd=no; else PKG_CHECK_MODULES(SYSTEMD, - [libsystemd-login >= 32, libsystemd-daemon >= 32], + [libsystemd-login >= 32, libsystemd-daemon >= 32, libsystemd-journal >= 32], have_systemd=yes, have_systemd=no) fi diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c index f2386b5..ad88d07 100644 --- a/dbus/dbus-spawn.c +++ b/dbus/dbus-spawn.c @@ -38,6 +38,9 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_SYSTEMD +#include +#endif extern char **environ; @@ -1150,6 +1153,10 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, int child_err_report_pipe[2] = { -1, -1 }; int babysitter_pipe[2] = { -1, -1 }; pid_t pid; +#ifdef HAVE_SYSTEMD + int fd_out = -1; + int fd_err = -1; +#endif _DBUS_ASSERT_ERROR_IS_CLEAR (error); _dbus_assert (argv[0] != NULL); @@ -1236,7 +1243,13 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, } _DBUS_ASSERT_ERROR_IS_CLEAR (error); - + +#ifdef HAVE_SYSTEMD + /* this may fail, but not critical */ + fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE); + fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE); +#endif + pid = fork (); if (pid < 0) @@ -1276,6 +1289,15 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, */ signal (SIGPIPE, SIG_IGN); +#ifdef HAVE_SYSTEMD + /* log to systemd journal */ + if (fd_out >= 0) + dup2 (fd_out, STDOUT_FILENO); + if (fd_err >= 0) + dup2 (fd_err, STDERR_FILENO); + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif do_exec (child_err_report_pipe[WRITE_END], argv, env, @@ -1284,6 +1306,10 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, } else { +#ifdef HAVE_SYSTEMD + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif babysit (grandchild_pid, babysitter_pipe[1]); _dbus_assert_not_reached ("Got to code after babysit()"); } @@ -1293,6 +1319,10 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, /* Close the uncared-about ends of the pipes */ close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[1]); +#ifdef HAVE_SYSTEMD + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif sitter->socket_to_babysitter = babysitter_pipe[0]; babysitter_pipe[0] = -1; @@ -1322,6 +1352,10 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[0]); close_and_invalidate (&babysitter_pipe[1]); +#ifdef HAVE_SYSTEMD + close_and_invalidate (&fd_out); + close_and_invalidate (&fd_err); +#endif if (sitter != NULL) _dbus_babysitter_unref (sitter); -- 1.7.9.5