|
|
9fa8e4 |
From cb356d992cec51cb87e2243edadec6a3d3348bd7 Mon Sep 17 00:00:00 2001
|
|
|
9fa8e4 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
9fa8e4 |
Date: Tue, 19 Jul 2016 16:54:43 -0400
|
|
|
9fa8e4 |
Subject: [PATCH 1/3] xdmcp-display-factory: notify remote display when session
|
|
|
9fa8e4 |
ended
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gnome-shell and the session dbus daemon don't automatically exit
|
|
|
9fa8e4 |
when gnome-session does. They, instead, wait for the display to
|
|
|
9fa8e4 |
exit or regenerate. If the display is remote, that won't happen
|
|
|
9fa8e4 |
until the keep alive timeout.
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
This commit changes GDM to explicitly notify the remote display
|
|
|
9fa8e4 |
when the session is over, so that it can regenerate immediately.
|
|
|
9fa8e4 |
---
|
|
|
9fa8e4 |
daemon/gdm-xdmcp-display-factory.c | 15 ++++++++++++++-
|
|
|
9fa8e4 |
1 file changed, 14 insertions(+), 1 deletion(-)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
|
|
|
9fa8e4 |
index d01f7ff..4132dd1 100644
|
|
|
9fa8e4 |
--- a/daemon/gdm-xdmcp-display-factory.c
|
|
|
9fa8e4 |
+++ b/daemon/gdm-xdmcp-display-factory.c
|
|
|
9fa8e4 |
@@ -183,61 +183,64 @@ struct GdmXdmcpDisplayFactoryPrivate
|
|
|
9fa8e4 |
/* configuration */
|
|
|
9fa8e4 |
guint port;
|
|
|
9fa8e4 |
gboolean use_multicast;
|
|
|
9fa8e4 |
char *multicast_address;
|
|
|
9fa8e4 |
gboolean honor_indirect;
|
|
|
9fa8e4 |
char *willing_script;
|
|
|
9fa8e4 |
guint max_displays_per_host;
|
|
|
9fa8e4 |
guint max_displays;
|
|
|
9fa8e4 |
guint max_pending_displays;
|
|
|
9fa8e4 |
guint max_wait;
|
|
|
9fa8e4 |
guint max_wait_indirect;
|
|
|
9fa8e4 |
};
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
enum {
|
|
|
9fa8e4 |
PROP_0,
|
|
|
9fa8e4 |
PROP_PORT,
|
|
|
9fa8e4 |
PROP_USE_MULTICAST,
|
|
|
9fa8e4 |
PROP_MULTICAST_ADDRESS,
|
|
|
9fa8e4 |
PROP_HONOR_INDIRECT,
|
|
|
9fa8e4 |
PROP_WILLING_SCRIPT,
|
|
|
9fa8e4 |
PROP_MAX_DISPLAYS_PER_HOST,
|
|
|
9fa8e4 |
PROP_MAX_DISPLAYS,
|
|
|
9fa8e4 |
PROP_MAX_PENDING_DISPLAYS,
|
|
|
9fa8e4 |
PROP_MAX_WAIT,
|
|
|
9fa8e4 |
PROP_MAX_WAIT_INDIRECT,
|
|
|
9fa8e4 |
};
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void gdm_xdmcp_display_factory_class_init (GdmXdmcpDisplayFactoryClass *klass);
|
|
|
9fa8e4 |
static void gdm_xdmcp_display_factory_init (GdmXdmcpDisplayFactory *manager);
|
|
|
9fa8e4 |
static void gdm_xdmcp_display_factory_finalize (GObject *object);
|
|
|
9fa8e4 |
-
|
|
|
9fa8e4 |
+static void gdm_xdmcp_send_alive (GdmXdmcpDisplayFactory *factory,
|
|
|
9fa8e4 |
+ GdmAddress *address,
|
|
|
9fa8e4 |
+ CARD16 dspnum,
|
|
|
9fa8e4 |
+ CARD32 sessid);
|
|
|
9fa8e4 |
static gpointer xdmcp_display_factory_object = NULL;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
G_DEFINE_TYPE (GdmXdmcpDisplayFactory, gdm_xdmcp_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
/* Theory of operation:
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Process idles waiting for UDP packets on port 177.
|
|
|
9fa8e4 |
* Incoming packets are decoded and checked against tcp_wrapper.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* A typical session looks like this:
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Display sends Query/BroadcastQuery to Manager.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Manager selects an appropriate authentication scheme from the
|
|
|
9fa8e4 |
* display's list of supported ones and sends Willing/Unwilling.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Assuming the display accepts the auth. scheme it sends back a
|
|
|
9fa8e4 |
* Request.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* If the manager accepts to service the display (i.e. loadavg is low)
|
|
|
9fa8e4 |
* it sends back an Accept containing a unique SessionID. The
|
|
|
9fa8e4 |
* SessionID is stored in an accept queue by the Manager. Should the
|
|
|
9fa8e4 |
* manager refuse to start a session a Decline is sent to the display.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* The display returns a Manage request containing the supplied
|
|
|
9fa8e4 |
* SessionID. The manager will then start a session on the display. In
|
|
|
9fa8e4 |
* case the SessionID is not on the accept queue the manager returns
|
|
|
9fa8e4 |
* Refuse. If the manager fails to open the display for connections
|
|
|
9fa8e4 |
* Failed is returned.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
@@ -2026,68 +2029,78 @@ on_hostname_selected (GdmXdmcpChooserDisplay *display,
|
|
|
9fa8e4 |
g_warning ("Unable to get address: %s", gai_strerror (gaierr));
|
|
|
9fa8e4 |
g_free (xdmcp_port);
|
|
|
9fa8e4 |
return;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
g_free (xdmcp_port);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
/* just take the first one */
|
|
|
9fa8e4 |
ai = ai_list;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
if (ai != NULL) {
|
|
|
9fa8e4 |
char *ip;
|
|
|
9fa8e4 |
ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
ip = NULL;
|
|
|
9fa8e4 |
gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
|
|
|
9fa8e4 |
g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
|
|
|
9fa8e4 |
ip ? ip : "(null)");
|
|
|
9fa8e4 |
g_free (ip);
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
freeaddrinfo (ai_list);
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
on_display_status_changed (GdmDisplay *display,
|
|
|
9fa8e4 |
GParamSpec *arg1,
|
|
|
9fa8e4 |
GdmXdmcpDisplayFactory *factory)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
int status;
|
|
|
9fa8e4 |
GdmDisplayStore *store;
|
|
|
9fa8e4 |
+ GdmAddress *address;
|
|
|
9fa8e4 |
+ gint32 session_number;
|
|
|
9fa8e4 |
+ int display_number;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
status = gdm_display_get_status (display);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status);
|
|
|
9fa8e4 |
switch (status) {
|
|
|
9fa8e4 |
case GDM_DISPLAY_FINISHED:
|
|
|
9fa8e4 |
+ g_object_get (display,
|
|
|
9fa8e4 |
+ "remote-address", &address,
|
|
|
9fa8e4 |
+ "x11-display-number", &display_number,
|
|
|
9fa8e4 |
+ "session-number", &session_number,
|
|
|
9fa8e4 |
+ NULL);
|
|
|
9fa8e4 |
+ gdm_xdmcp_send_alive (factory, address, display_number, session_number);
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
gdm_display_store_remove (store, display);
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_FAILED:
|
|
|
9fa8e4 |
gdm_display_store_remove (store, display);
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_UNMANAGED:
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_PREPARED:
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_MANAGED:
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
default:
|
|
|
9fa8e4 |
g_assert_not_reached ();
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static GdmDisplay *
|
|
|
9fa8e4 |
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
|
|
|
9fa8e4 |
const char *hostname,
|
|
|
9fa8e4 |
GdmAddress *address,
|
|
|
9fa8e4 |
int displaynum)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
GdmDisplay *display;
|
|
|
9fa8e4 |
GdmDisplayStore *store;
|
|
|
9fa8e4 |
gboolean use_chooser;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
|
|
|
9fa8e4 |
hostname ? hostname : "(null)", displaynum);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
--
|
|
|
9fa8e4 |
2.7.4
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
From e35b483f4c32d4095ea0d67991fff1e2b8339f2c Mon Sep 17 00:00:00 2001
|
|
|
9fa8e4 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
9fa8e4 |
Date: Wed, 20 Jul 2016 11:43:45 -0400
|
|
|
9fa8e4 |
Subject: [PATCH 2/3] worker: kill process group when session exits
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
Send a hangup signal to the session pg when it exits, so things
|
|
|
9fa8e4 |
have a chance to get cleaned up.
|
|
|
9fa8e4 |
---
|
|
|
9fa8e4 |
daemon/gdm-session-worker.c | 2 ++
|
|
|
9fa8e4 |
1 file changed, 2 insertions(+)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
|
|
9fa8e4 |
index e07d32e..bc4a7ea 100644
|
|
|
9fa8e4 |
--- a/daemon/gdm-session-worker.c
|
|
|
9fa8e4 |
+++ b/daemon/gdm-session-worker.c
|
|
|
9fa8e4 |
@@ -1603,60 +1603,62 @@ run_script (GdmSessionWorker *worker,
|
|
|
9fa8e4 |
worker->priv->username,
|
|
|
9fa8e4 |
worker->priv->x11_display_name,
|
|
|
9fa8e4 |
worker->priv->display_is_local? NULL : worker->priv->hostname,
|
|
|
9fa8e4 |
worker->priv->x11_authority_file);
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
session_worker_child_watch (GPid pid,
|
|
|
9fa8e4 |
int status,
|
|
|
9fa8e4 |
GdmSessionWorker *worker)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
g_debug ("GdmSessionWorker: child (pid:%d) done (%s:%d)",
|
|
|
9fa8e4 |
(int) pid,
|
|
|
9fa8e4 |
WIFEXITED (status) ? "status"
|
|
|
9fa8e4 |
: WIFSIGNALED (status) ? "signal"
|
|
|
9fa8e4 |
: "unknown",
|
|
|
9fa8e4 |
WIFEXITED (status) ? WEXITSTATUS (status)
|
|
|
9fa8e4 |
: WIFSIGNALED (status) ? WTERMSIG (status)
|
|
|
9fa8e4 |
: -1);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#ifdef WITH_CONSOLE_KIT
|
|
|
9fa8e4 |
close_ck_session (worker);
|
|
|
9fa8e4 |
#endif
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gdm_dbus_worker_emit_session_exited (GDM_DBUS_WORKER (worker),
|
|
|
9fa8e4 |
worker->priv->service,
|
|
|
9fa8e4 |
status);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
+ killpg (pid, SIGHUP);
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
worker->priv->child_pid = -1;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
run_script (worker, GDMCONFDIR "/PostSession");
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
gdm_session_worker_watch_child (GdmSessionWorker *worker)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
g_debug ("GdmSession worker: watching pid %d", worker->priv->child_pid);
|
|
|
9fa8e4 |
worker->priv->child_watch_id = g_child_watch_add (worker->priv->child_pid,
|
|
|
9fa8e4 |
(GChildWatchFunc)session_worker_child_watch,
|
|
|
9fa8e4 |
worker);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static gboolean
|
|
|
9fa8e4 |
_is_loggable_file (const char* filename)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
struct stat file_info;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
if (g_lstat (filename, &file_info) < 0) {
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
rotate_logs (const char *path,
|
|
|
9fa8e4 |
guint n_copies)
|
|
|
9fa8e4 |
--
|
|
|
9fa8e4 |
2.7.4
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
From fa6bc4c99f49a9c6ccd5cf1728eabf71685c34d0 Mon Sep 17 00:00:00 2001
|
|
|
9fa8e4 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
9fa8e4 |
Date: Wed, 20 Jul 2016 17:23:05 -0400
|
|
|
9fa8e4 |
Subject: [PATCH 3/3] slave: close display when we're done with it.
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
When we're done with the display we need to kill off any clients
|
|
|
9fa8e4 |
that are lingering and close our own connection to the display.
|
|
|
9fa8e4 |
---
|
|
|
9fa8e4 |
configure.ac | 2 +-
|
|
|
9fa8e4 |
daemon/gdm-slave.c | 38 ++++++++++++++++++++++++++++++++++++++
|
|
|
9fa8e4 |
2 files changed, 39 insertions(+), 1 deletion(-)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
diff --git a/configure.ac b/configure.ac
|
|
|
9fa8e4 |
index a131535..1ac2801 100644
|
|
|
9fa8e4 |
--- a/configure.ac
|
|
|
9fa8e4 |
+++ b/configure.ac
|
|
|
9fa8e4 |
@@ -63,61 +63,61 @@ dnl ---------------------------------------------------------------------------
|
|
|
9fa8e4 |
GLIB_REQUIRED_VERSION=2.36.0
|
|
|
9fa8e4 |
GTK_REQUIRED_VERSION=2.91.1
|
|
|
9fa8e4 |
LIBCANBERRA_GTK_REQUIRED_VERSION=0.4
|
|
|
9fa8e4 |
ACCOUNTS_SERVICE_REQUIRED_VERSION=0.6.12
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
EXTRA_COMPILE_WARNINGS(yes)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
|
|
|
9fa8e4 |
AC_SUBST(GTHREAD_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(GTHREAD_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(COMMON,
|
|
|
9fa8e4 |
gobject-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-unix-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(COMMON_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(COMMON_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(DAEMON,
|
|
|
9fa8e4 |
gobject-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-unix-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
accountsservice >= $ACCOUNTS_SERVICE_REQUIRED_VERSION
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(DAEMON_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(DAEMON_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
GLIB_GSETTINGS
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
-PKG_CHECK_MODULES(XLIB, x11 xau xrandr, ,
|
|
|
9fa8e4 |
+PKG_CHECK_MODULES(XLIB, x11 xau xrandr x11-xcb, ,
|
|
|
9fa8e4 |
[AC_PATH_XTRA
|
|
|
9fa8e4 |
if test "x$no_x" = xyes; then
|
|
|
9fa8e4 |
AC_MSG_ERROR("no (requires X development libraries)")
|
|
|
9fa8e4 |
else
|
|
|
9fa8e4 |
XLIB_LIBS="$X_PRE_LIBS $X_LIBS -lXau -lX11 -lXext -lXrandr $X_EXTRA_LIBS"
|
|
|
9fa8e4 |
XLIB_CFLAGS=$X_CFLAGS
|
|
|
9fa8e4 |
fi])
|
|
|
9fa8e4 |
AC_SUBST(XLIB_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(XLIB_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(GTK,
|
|
|
9fa8e4 |
gtk+-3.0 >= $GTK_REQUIRED_VERSION
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(GTK_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(GTK_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(CANBERRA_GTK,
|
|
|
9fa8e4 |
libcanberra-gtk3 >= $LIBCANBERRA_GTK_REQUIRED_VERSION
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(CANBERRA_GTK_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(CANBERRA_GTK_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
AC_ARG_WITH(selinux,
|
|
|
9fa8e4 |
AS_HELP_STRING([--with-selinux],
|
|
|
9fa8e4 |
[Add SELinux support]),,
|
|
|
9fa8e4 |
with_selinux=auto)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(LIBSELINUX, libselinux, have_selinux=yes, have_selinux=no)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
use_selinux=no
|
|
|
9fa8e4 |
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
|
|
|
9fa8e4 |
index b4bbcfd..3a22cc6 100644
|
|
|
9fa8e4 |
--- a/daemon/gdm-slave.c
|
|
|
9fa8e4 |
+++ b/daemon/gdm-slave.c
|
|
|
9fa8e4 |
@@ -11,65 +11,68 @@
|
|
|
9fa8e4 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
9fa8e4 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
9fa8e4 |
* GNU General Public License for more details.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* You should have received a copy of the GNU General Public License
|
|
|
9fa8e4 |
* along with this program; if not, write to the Free Software
|
|
|
9fa8e4 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
*/
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "config.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include <stdlib.h>
|
|
|
9fa8e4 |
#include <stdio.h>
|
|
|
9fa8e4 |
#include <stdint.h>
|
|
|
9fa8e4 |
#include <fcntl.h>
|
|
|
9fa8e4 |
#include <unistd.h>
|
|
|
9fa8e4 |
#include <string.h>
|
|
|
9fa8e4 |
#include <sys/types.h>
|
|
|
9fa8e4 |
#include <sys/wait.h>
|
|
|
9fa8e4 |
#include <errno.h>
|
|
|
9fa8e4 |
#include <pwd.h>
|
|
|
9fa8e4 |
#include <grp.h>
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include <glib.h>
|
|
|
9fa8e4 |
#include <glib/gstdio.h>
|
|
|
9fa8e4 |
#include <glib/gi18n.h>
|
|
|
9fa8e4 |
#include <glib-object.h>
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include <X11/Xlib.h> /* for Display */
|
|
|
9fa8e4 |
+#include <X11/Xlib-xcb.h>
|
|
|
9fa8e4 |
#include <X11/Xatom.h> /* for XA_PIXMAP */
|
|
|
9fa8e4 |
#include <X11/cursorfont.h> /* for watch cursor */
|
|
|
9fa8e4 |
#include <X11/extensions/Xrandr.h>
|
|
|
9fa8e4 |
#include <X11/Xatom.h>
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
+#include <xcb/xcb.h>
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
#ifdef WITH_SYSTEMD
|
|
|
9fa8e4 |
#include <systemd/sd-login.h>
|
|
|
9fa8e4 |
#endif
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "gdm-common.h"
|
|
|
9fa8e4 |
#include "gdm-xerrors.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "gdm-slave.h"
|
|
|
9fa8e4 |
#include "gdm-display.h"
|
|
|
9fa8e4 |
#include "gdm-display-glue.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "gdm-server.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#define GDM_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SLAVE, GdmSlavePrivate))
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
struct GdmSlavePrivate
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
GPid pid;
|
|
|
9fa8e4 |
guint output_watch_id;
|
|
|
9fa8e4 |
guint error_watch_id;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
Display *server_display;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
char *session_id;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
GdmDisplay *display;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
/* cached display values */
|
|
|
9fa8e4 |
char *display_name;
|
|
|
9fa8e4 |
int display_number;
|
|
|
9fa8e4 |
@@ -453,60 +456,95 @@ gdm_slave_real_start (GdmSlave *slave)
|
|
|
9fa8e4 |
g_error_free (error);
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
error = NULL;
|
|
|
9fa8e4 |
res = gdm_display_get_seat_id (slave->priv->display, &slave->priv->display_seat_id, &error);
|
|
|
9fa8e4 |
if (! res) {
|
|
|
9fa8e4 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
9fa8e4 |
g_error_free (error);
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
error = NULL;
|
|
|
9fa8e4 |
res = gdm_display_is_initial (slave->priv->display, &slave->priv->display_is_initial, &error);
|
|
|
9fa8e4 |
if (! res) {
|
|
|
9fa8e4 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
9fa8e4 |
g_error_free (error);
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
return TRUE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static gboolean
|
|
|
9fa8e4 |
gdm_slave_real_stop (GdmSlave *slave)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
g_debug ("GdmSlave: Stopping slave");
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_clear_object (&slave->priv->display);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
+ if (slave->priv->server_display) {
|
|
|
9fa8e4 |
+ xcb_connection_t *connection;
|
|
|
9fa8e4 |
+ const xcb_setup_t *setup;
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ /* These 3 bits are reserved/unused by the X protocol */
|
|
|
9fa8e4 |
+ guint32 unused_bits = 0b11100000000000000000000000000000;
|
|
|
9fa8e4 |
+ XID highest_client, client;
|
|
|
9fa8e4 |
+ guint32 client_increment;
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ connection = XGetXCBConnection (slave->priv->server_display);
|
|
|
9fa8e4 |
+ setup = xcb_get_setup (connection);
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ /* resource_id_mask is the bits given to each client for
|
|
|
9fa8e4 |
+ * addressing resources */
|
|
|
9fa8e4 |
+ highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
|
|
|
9fa8e4 |
+ client_increment = setup->resource_id_mask + 1;
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ gdm_error_trap_push ();
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ /* Kill every client but ourselves, then close our own connection
|
|
|
9fa8e4 |
+ */
|
|
|
9fa8e4 |
+ for (client = 0;
|
|
|
9fa8e4 |
+ client <= highest_client;
|
|
|
9fa8e4 |
+ client += client_increment) {
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ if (client != setup->resource_id_base)
|
|
|
9fa8e4 |
+ XKillClient (slave->priv->server_display, client);
|
|
|
9fa8e4 |
+ }
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ XCloseDisplay (slave->priv->server_display);
|
|
|
9fa8e4 |
+ gdm_error_trap_pop ();
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
+ slave->priv->server_display = NULL;
|
|
|
9fa8e4 |
+ }
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
return TRUE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gboolean
|
|
|
9fa8e4 |
gdm_slave_start (GdmSlave *slave)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
gboolean ret;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmSlave: starting slave");
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_object_ref (slave);
|
|
|
9fa8e4 |
ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
|
|
|
9fa8e4 |
g_object_unref (slave);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
return ret;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gboolean
|
|
|
9fa8e4 |
gdm_slave_stop (GdmSlave *slave)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
gboolean ret;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmSlave: stopping slave");
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_object_ref (slave);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
--
|
|
|
9fa8e4 |
2.7.4
|
|
|
9fa8e4 |
|