mirror of https://github.com/neutrinolabs/xrdp
Add xrdp-waitforx to wait for X to start with RandR outputs
For some window managers (fvwm2 and fvwm3) if the X server isn't running and has output it's possible for the window manager to fail or reconfigure randr incorrectly. With xrdp-waitfox: - Install xrdp-waitfox to the BIN dir. - sesman will run xrdp-waitfox as the logged in user. - Set an alarm to exit after 30 seconds. - Try to open env DISPLAY value's display (10 seconds). - Test for RandR extension. - Wait for outputs to appear (10 seconds).
This commit is contained in:
parent
9bab8e0da5
commit
829378bba8
|
@ -58,6 +58,7 @@ SUBDIRS = \
|
||||||
xrdp \
|
xrdp \
|
||||||
fontutils \
|
fontutils \
|
||||||
keygen \
|
keygen \
|
||||||
|
waitforx \
|
||||||
docs \
|
docs \
|
||||||
instfiles \
|
instfiles \
|
||||||
genkeymap \
|
genkeymap \
|
||||||
|
|
|
@ -575,6 +575,7 @@ AC_CONFIG_FILES([
|
||||||
instfiles/pulse/Makefile
|
instfiles/pulse/Makefile
|
||||||
instfiles/rc.d/Makefile
|
instfiles/rc.d/Makefile
|
||||||
keygen/Makefile
|
keygen/Makefile
|
||||||
|
waitforx/Makefile
|
||||||
libipm/Makefile
|
libipm/Makefile
|
||||||
libxrdp/Makefile
|
libxrdp/Makefile
|
||||||
Makefile
|
Makefile
|
||||||
|
|
|
@ -5,6 +5,7 @@ AM_CPPFLAGS = \
|
||||||
-DXRDP_SYSCONF_PATH=\"${sysconfdir}\" \
|
-DXRDP_SYSCONF_PATH=\"${sysconfdir}\" \
|
||||||
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
|
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
|
||||||
-DXRDP_SBIN_PATH=\"${sbindir}\" \
|
-DXRDP_SBIN_PATH=\"${sbindir}\" \
|
||||||
|
-DXRDP_BIN_PATH=\"${bindir}\" \
|
||||||
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
|
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
|
||||||
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
|
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
|
||||||
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
||||||
|
@ -34,7 +35,9 @@ xrdp_sesman_SOURCES = \
|
||||||
sig.c \
|
sig.c \
|
||||||
sig.h \
|
sig.h \
|
||||||
xauth.c \
|
xauth.c \
|
||||||
xauth.h
|
xauth.h \
|
||||||
|
xwait.c \
|
||||||
|
xwait.h
|
||||||
|
|
||||||
# Possible authentication modules
|
# Possible authentication modules
|
||||||
# See https://www.gnu.org/software/automake/manual/html_node/Conditional-Sources.html
|
# See https://www.gnu.org/software/automake/manual/html_node/Conditional-Sources.html
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "sesman.h"
|
#include "sesman.h"
|
||||||
#include "string_calls.h"
|
#include "string_calls.h"
|
||||||
#include "xauth.h"
|
#include "xauth.h"
|
||||||
|
#include "xwait.h"
|
||||||
#include "xrdp_sockets.h"
|
#include "xrdp_sockets.h"
|
||||||
|
|
||||||
#ifndef PR_SET_NO_NEW_PRIVS
|
#ifndef PR_SET_NO_NEW_PRIVS
|
||||||
|
@ -285,42 +286,6 @@ x_server_running_check_ports(int display)
|
||||||
return x_running;
|
return x_running;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @brief checks if there's a server running on a display
|
|
||||||
* @param display the display to check
|
|
||||||
* @return 0 if there isn't a display running, nonzero otherwise
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
x_server_running(int display)
|
|
||||||
{
|
|
||||||
char text[256];
|
|
||||||
int x_running;
|
|
||||||
|
|
||||||
g_sprintf(text, "/tmp/.X11-unix/X%d", display);
|
|
||||||
x_running = g_file_exist(text);
|
|
||||||
|
|
||||||
if (!x_running)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
|
||||||
g_sprintf(text, "/tmp/.X%d-lock", display);
|
|
||||||
x_running = g_file_exist(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x_running)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return x_running;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* called with the main thread
|
/* called with the main thread
|
||||||
returns boolean */
|
returns boolean */
|
||||||
|
@ -375,37 +340,6 @@ session_get_avail_display_from_chain(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
static int
|
|
||||||
wait_for_xserver(int display)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* give X a bit to start */
|
|
||||||
/* wait up to 10 secs for x server to start */
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
|
|
||||||
|
|
||||||
while (!x_server_running(display))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i > 40)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_WARNING,
|
|
||||||
"Timed out waiting for X server on display %d to startup",
|
|
||||||
display);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_sleep(250);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
static int
|
static int
|
||||||
session_start_chansrv(int uid, int display)
|
session_start_chansrv(int uid, int display)
|
||||||
{
|
{
|
||||||
|
@ -655,13 +589,12 @@ session_start(struct auth_info *auth_info,
|
||||||
}
|
}
|
||||||
else if (window_manager_pid == 0)
|
else if (window_manager_pid == 0)
|
||||||
{
|
{
|
||||||
wait_for_xserver(display);
|
|
||||||
env_set_user(s->uid,
|
env_set_user(s->uid,
|
||||||
0,
|
0,
|
||||||
display,
|
display,
|
||||||
g_cfg->env_names,
|
g_cfg->env_names,
|
||||||
g_cfg->env_values);
|
g_cfg->env_values);
|
||||||
if (x_server_running(display))
|
if (wait_for_xserver(display))
|
||||||
{
|
{
|
||||||
auth_set_env(auth_info);
|
auth_set_env(auth_info);
|
||||||
if (s->directory != 0)
|
if (s->directory != 0)
|
||||||
|
@ -912,7 +845,6 @@ session_start(struct auth_info *auth_info,
|
||||||
struct exit_status xserver_exit_status;
|
struct exit_status xserver_exit_status;
|
||||||
struct exit_status chansrv_exit_status;
|
struct exit_status chansrv_exit_status;
|
||||||
|
|
||||||
wait_for_xserver(display);
|
|
||||||
chansrv_pid = session_start_chansrv(s->uid, display);
|
chansrv_pid = session_start_chansrv(s->uid, display);
|
||||||
|
|
||||||
LOG(LOG_LEVEL_INFO,
|
LOG(LOG_LEVEL_INFO,
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include "config_ac.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "os_calls.h"
|
||||||
|
#include "string_calls.h"
|
||||||
|
#include "xwait.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int
|
||||||
|
wait_for_xserver(int display)
|
||||||
|
{
|
||||||
|
FILE *dp = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
char buffer[100];
|
||||||
|
char exe_cmd[262];
|
||||||
|
|
||||||
|
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
|
||||||
|
|
||||||
|
g_snprintf(exe_cmd, sizeof(exe_cmd), "%s/xrdp-waitforx", XRDP_BIN_PATH);
|
||||||
|
dp = popen(exe_cmd, "r");
|
||||||
|
if (dp == NULL)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "Unable to launch xrdp-waitforx");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(buffer, 100, dp))
|
||||||
|
{
|
||||||
|
g_strtrim(buffer, 2);
|
||||||
|
LOG(LOG_LEVEL_DEBUG, "%s", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pclose(dp);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "An error occurred while running xrdp-waitforx");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef XWAIT_H
|
||||||
|
#define XWAIT_H
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @brief waits for X to start
|
||||||
|
* @param display number
|
||||||
|
* @return 0 on error, 1 if X has outputs
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
wait_for_xserver(int display);
|
||||||
|
#endif
|
|
@ -0,0 +1,10 @@
|
||||||
|
bin_PROGRAMS = \
|
||||||
|
xrdp-waitforx
|
||||||
|
|
||||||
|
AM_LDFLAGS = -lX11 -lXrandr
|
||||||
|
AM_CFLAGS = -I$(top_srcdir)/common
|
||||||
|
|
||||||
|
xrdp_waitforx_SOURCES = waitforx.c
|
||||||
|
|
||||||
|
xrdp_waitforx_LDADD = \
|
||||||
|
$(top_builddir)/common/libcommon.la
|
|
@ -0,0 +1,96 @@
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define ATTEMPTS 10
|
||||||
|
#define ALARM_WAIT 30
|
||||||
|
|
||||||
|
void
|
||||||
|
alarm_handler(int signal_num)
|
||||||
|
{
|
||||||
|
printf("Unable to find RandR outputs after %d seconds\n", ALARM_WAIT);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *display = NULL;
|
||||||
|
int error_base = 0;
|
||||||
|
int event_base = 0;
|
||||||
|
int n = 0;
|
||||||
|
int outputs = 0;
|
||||||
|
int wait = ATTEMPTS;
|
||||||
|
|
||||||
|
Display *dpy = NULL;
|
||||||
|
XRRScreenResources *res = NULL;
|
||||||
|
|
||||||
|
display = getenv("DISPLAY");
|
||||||
|
|
||||||
|
signal(SIGALRM, alarm_handler);
|
||||||
|
alarm(ALARM_WAIT);
|
||||||
|
|
||||||
|
if (!display)
|
||||||
|
{
|
||||||
|
printf("DISPLAY is null");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 1; n <= wait; ++n)
|
||||||
|
{
|
||||||
|
dpy = XOpenDisplay(display);
|
||||||
|
printf("Opening display %s. Attempt %d of %d\n", display, n, wait);
|
||||||
|
if (dpy != NULL)
|
||||||
|
{
|
||||||
|
printf("Opened display %s\n", display);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dpy)
|
||||||
|
{
|
||||||
|
printf("Unable to open display %s\n", display);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!XRRQueryExtension(dpy, &event_base, &error_base))
|
||||||
|
{
|
||||||
|
printf("RandR not supported on display %s", display);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (n = 1; n <= wait; ++n)
|
||||||
|
{
|
||||||
|
res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
|
||||||
|
printf("Waiting for outputs. Attempt %d of %d\n", n, wait);
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
if (res->noutput > 0)
|
||||||
|
{
|
||||||
|
outputs = res->noutput;
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
printf("Found %d output[s]\n", outputs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
}
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputs > 0)
|
||||||
|
{
|
||||||
|
printf("display %s ready with %d outputs\n", display, res->noutput);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Unable to find any outputs\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
Loading…
Reference in New Issue