Adding D-Bus mailing list to Cc; questions about the user bus are significant for D-Bus as well as for systemd --user, and modifications of dbus-launch doubly so.
On 08/01/15 11:55, Colin Guthrie wrote: > I've got a modified dbus-launch that can be slotted in nicely I'm happy for dbus to get better integration with systemd --user (and I plan to work on it myself at some point) but I would much prefer dbus-launch to not be the way it happens. Modifying dbus-launch is fine for experimentation, but I would really like it to become a historical curiosity for people with bizarre multi-machine X11. It's fairly horrible code and there has never really been a canonical list of what is and isn't intended to work. Instead of altering dbus-launch, I would very much prefer to give libdbus/GDBus/etc. a better thing they can try before calling dbus-launch; I believe the current suggestion is looking for a Unix socket in XDG_RUNTIME_DIR/bus (formerly XDG_RUNTIME_DIR/dbus/user_bus_socket like in user-session-units). In particular, on Wayland systems, I would like dbus-launch to be something that is not relevant and never has been. Related: https://bugs.freedesktop.org/show_bug.cgi?id=61301 https://bugs.freedesktop.org/show_bug.cgi?id=61303 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=681241 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=774626 > It also pokes systemd --user with the environment > too. I attach a prototype of a standalone dbus-update-activation-environment tool, left over from last time I looked into this. It pokes all of its environment variables into both dbus-daemon (required) and "systemd --user" (if present), then execs its arguments. It is untested, and should probably upload variables specified by command-line arguments rather than all of them, and exit 0 rather than exec'ing an argument; but it's a start. I think having the X session or PAM stack do something similar to that is likely to be a better approach to compatibility with code that assumes environment variables propagate through the whole session (e.g. Debian's Xsession.d) than having dbus-launch grow yet more magic. The observant will notice that I have not attached it to a feature request or anything; that's because it probably doesn't work yet, I got halfway through prototyping it. > The issue I currently have is that the dbus daemon itself is now part of > the user@.service cgroup and NOT part of the session cgroup I think that's unavoidable; if we want any services that exist outside the scope of an individual login session, then this is how they are going to have to work. > In GNOME for example, gnome-terminal is started via dbus activation > (gnome-terminal-server). I think that's OK. Anything "in the foreground" whose lifetime is tied to the shell will die from SIGHUP when gnome-terminal exits because the terminal got disconnected from X11. Meanwhile, anything that has done the usual shell things to go to the background, or is in a screen or tmux, ends up in the same situation as a D-Bus session service or a systemd user service: it survives for exactly as long as systemd --user (which might persist after last-logout, or not, according to sysadmin configuration) and then dies. Either way, it seems like what you want? As I understand it, the supported situations are "systemd --user lasts longer than the X11 session" (for normal use) and "systemd --user lasts exactly as long as the X11 session" (for shared computers where the sysadmin wants to avoid non-session processes hanging around), but not "systemd --user exits before the X11 session does". S
#include <errno.h> #include <error.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sysexits.h> #include <unistd.h> #include <dbus/dbus.h> #define THIS "debian-dbus-upload-environment" extern char **environ; static void oom (void) __attribute__ ((__noreturn__)); static void oom (void) { fprintf (stderr, "%s: out of memory\n", THIS); _exit (EX_UNAVAILABLE); } static dbus_bool_t systemd_user_running (void) { char *xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR"); char *path; struct stat buf; if (xdg_runtime_dir == NULL) return FALSE; /* assume that XDG_RUNTIME_DIR/systemd exists if and only if * "systemd --user" is running */ if (asprintf (&path, "%s/systemd", xdg_runtime_dir) < 0) oom (); if (stat (path, &buf) < 0) return FALSE; free (path); return TRUE; } int main (int argc, char **argv) { char **next = NULL; char **envp; DBusConnection *conn; DBusMessage *msg; DBusMessage *sd_msg; DBusMessage *reply; DBusError error = DBUS_ERROR_INIT; DBusMessageIter msg_iter; DBusMessageIter sd_msg_iter; DBusMessageIter array_iter; DBusMessageIter sd_array_iter; int i; struct stat stat_buf; for (i = 1; i < argc; i++) { if (strcmp (argv[i], "--") == 0 && (i + 1) < argc) { next = argv + i + 1; break; } else { fprintf (stderr, "%s: usage:\n" "%s [-- next-executable [arguments...]]\n", THIS, THIS); return EX_USAGE; } } conn = dbus_bus_get (DBUS_BUS_SESSION, &error); if (conn == NULL) { fprintf (stderr, "%s: error: unable to connect to D-Bus: %s\n", THIS, error.message); return EX_OSERR; } msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "UpdateActivationEnvironment"); if (msg == NULL) oom (); sd_msg = dbus_message_new_method_call ("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SetEnvironment"); if (sd_msg == NULL) oom (); dbus_message_iter_init_append (msg, &msg_iter); dbus_message_iter_open_container (&msg_iter, DBUS_TYPE_ARRAY, "{ss}", &array_iter); dbus_message_iter_open_container (&sd_msg_iter, DBUS_TYPE_ARRAY, "{ss}", &sd_array_iter); for (envp = environ; *envp != NULL; envp++) { char *copy; char *eq; char *val; DBusMessageIter pair_iter; if (!dbus_validate_utf8 (*envp, NULL)) { fprintf (stderr, "%s: warning: environment variable not UTF-8: %s\n", THIS, *envp); continue; } copy = strdup (*envp); if (copy == NULL) oom (); eq = strchr (copy, '='); if (eq == NULL) { fprintf (stderr, "%s: warning: environment variable without '=': %s\n", THIS, copy); free (copy); continue; } *eq = '\0'; val = eq + 1; if (!dbus_message_iter_append_basic (&sd_array_iter, DBUS_TYPE_STRING, envp)) oom (); if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_DICT_ENTRY, NULL, &pair_iter)) oom (); if (!dbus_message_iter_append_basic (&pair_iter, DBUS_TYPE_STRING, ©)) oom (); if (!dbus_message_iter_append_basic (&pair_iter, DBUS_TYPE_STRING, &val)) oom (); if (!dbus_message_iter_close_container (&array_iter, &pair_iter)) oom (); free (copy); } if (!dbus_message_iter_close_container (&msg_iter, &array_iter)) oom (); if (!dbus_message_iter_close_container (&sd_msg_iter, &sd_array_iter)) oom (); reply = dbus_connection_send_with_reply_and_block (conn, msg, -1, &error); if (reply == NULL) { fprintf (stderr, "%s: error sending to dbus-daemon: %s: %s\n", THIS, error.name, error.message); return EX_UNAVAILABLE; } if (!dbus_message_get_args (msg, &error, DBUS_TYPE_INVALID)) { fprintf (stderr, "%s: error from dbus-daemon: %s: %s\n", THIS, error.name, error.message); return EX_UNAVAILABLE; } dbus_message_unref (reply); if (systemd_user_running ()) { reply = dbus_connection_send_with_reply_and_block (conn, sd_msg, -1, &error); /* non-fatal, the main purpose of this thing is to communicate * with dbus-daemon */ if (reply == NULL) { fprintf (stderr, "%s: error sending to systemd: %s: %s\n", THIS, error.name, error.message); } else if (!dbus_message_get_args (msg, &error, DBUS_TYPE_INVALID)) { fprintf (stderr, "%s: error from systemd: %s: %s\n", THIS, error.name, error.message); } } if (next != NULL) { execvp (next[0], next); fprintf (stderr, "%s: error: cannot execute %s: %s\n", THIS, next[0], strerror (errno)); return EX_UNAVAILABLE; } return 0; }
_______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel