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 [email protected] 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
[email protected]
http://lists.freedesktop.org/mailman/listinfo/systemd-devel