Merge pull request #2492 from derekschrock/randr-wait
Add xrdp-waitforx to wait for X to start with RandR outputs
This commit is contained in:
commit
a27440c237
@ -58,6 +58,7 @@ SUBDIRS = \
|
||||
xrdp \
|
||||
fontutils \
|
||||
keygen \
|
||||
waitforx \
|
||||
docs \
|
||||
instfiles \
|
||||
genkeymap \
|
||||
|
@ -2808,6 +2808,22 @@ g_execlp3(const char *a1, const char *a2, const char *a3)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32 */
|
||||
unsigned int
|
||||
g_set_alarm(void (*func)(int), unsigned int secs)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return 0;
|
||||
#else
|
||||
/* Cancel any previous alarm to prevent a race */
|
||||
unsigned int rv = alarm(0);
|
||||
signal(SIGALRM, func);
|
||||
(void)alarm(secs);
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32 */
|
||||
void
|
||||
|
@ -204,6 +204,7 @@ char *g_get_strerror(void);
|
||||
int g_get_errno(void);
|
||||
int g_execvp(const char *p1, char *args[]);
|
||||
int g_execlp3(const char *a1, const char *a2, const char *a3);
|
||||
unsigned int g_set_alarm(void (*func)(int), unsigned int secs);
|
||||
void g_signal_child_stop(void (*func)(int));
|
||||
void g_signal_segfault(void (*func)(int));
|
||||
void g_signal_hang_up(void (*func)(int));
|
||||
|
@ -575,6 +575,7 @@ AC_CONFIG_FILES([
|
||||
instfiles/pulse/Makefile
|
||||
instfiles/rc.d/Makefile
|
||||
keygen/Makefile
|
||||
waitforx/Makefile
|
||||
libipm/Makefile
|
||||
libxrdp/Makefile
|
||||
Makefile
|
||||
|
@ -5,6 +5,7 @@ AM_CPPFLAGS = \
|
||||
-DXRDP_SYSCONF_PATH=\"${sysconfdir}\" \
|
||||
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
|
||||
-DXRDP_SBIN_PATH=\"${sbindir}\" \
|
||||
-DXRDP_BIN_PATH=\"${bindir}\" \
|
||||
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
|
||||
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
|
||||
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
||||
@ -34,7 +35,9 @@ xrdp_sesman_SOURCES = \
|
||||
sig.c \
|
||||
sig.h \
|
||||
xauth.c \
|
||||
xauth.h
|
||||
xauth.h \
|
||||
xwait.c \
|
||||
xwait.h
|
||||
|
||||
# Possible authentication modules
|
||||
# See https://www.gnu.org/software/automake/manual/html_node/Conditional-Sources.html
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "sesman.h"
|
||||
#include "string_calls.h"
|
||||
#include "xauth.h"
|
||||
#include "xwait.h"
|
||||
#include "xrdp_sockets.h"
|
||||
|
||||
#ifndef PR_SET_NO_NEW_PRIVS
|
||||
@ -285,42 +286,6 @@ x_server_running_check_ports(int display)
|
||||
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
|
||||
returns boolean */
|
||||
@ -375,37 +340,6 @@ session_get_avail_display_from_chain(void)
|
||||
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
|
||||
session_start_chansrv(int uid, int display)
|
||||
{
|
||||
@ -655,13 +589,12 @@ session_start(struct auth_info *auth_info,
|
||||
}
|
||||
else if (window_manager_pid == 0)
|
||||
{
|
||||
wait_for_xserver(display);
|
||||
env_set_user(s->uid,
|
||||
0,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
g_cfg->env_values);
|
||||
if (x_server_running(display))
|
||||
if (wait_for_xserver(display))
|
||||
{
|
||||
auth_set_env(auth_info);
|
||||
if (s->directory != 0)
|
||||
@ -912,7 +845,6 @@ session_start(struct auth_info *auth_info,
|
||||
struct exit_status xserver_exit_status;
|
||||
struct exit_status chansrv_exit_status;
|
||||
|
||||
wait_for_xserver(display);
|
||||
chansrv_pid = session_start_chansrv(s->uid, display);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
|
47
sesman/xwait.c
Normal file
47
sesman/xwait.c
Normal file
@ -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;
|
||||
}
|
12
sesman/xwait.h
Normal file
12
sesman/xwait.h
Normal file
@ -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
|
10
waitforx/Makefile.am
Normal file
10
waitforx/Makefile.am
Normal file
@ -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
|
101
waitforx/waitforx.c
Normal file
101
waitforx/waitforx.c
Normal file
@ -0,0 +1,101 @@
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config_ac.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#define ATTEMPTS 10
|
||||
#define ALARM_WAIT 30
|
||||
|
||||
void
|
||||
alarm_handler(int signal_num)
|
||||
{
|
||||
/* Avoid printf() in signal handler (see signal-safety(7)) */
|
||||
const char msg[] = "Timed out waiting for RandR outputs\n";
|
||||
g_file_write(1, msg, g_strlen(msg));
|
||||
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");
|
||||
|
||||
g_set_alarm(alarm_handler, 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;
|
||||
}
|
||||
g_sleep(1000);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
g_sleep(1000);
|
||||
}
|
||||
|
||||
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
Block a user