Skip to content

Commit a27440c

Browse files
authored
Merge pull request #2492 from derekschrock/randr-wait
Add xrdp-waitforx to wait for X to start with RandR outputs
2 parents f3dc944 + cb39b84 commit a27440c

File tree

10 files changed

+195
-71
lines changed

10 files changed

+195
-71
lines changed

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ SUBDIRS = \
5858
xrdp \
5959
fontutils \
6060
keygen \
61+
waitforx \
6162
docs \
6263
instfiles \
6364
genkeymap \

common/os_calls.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2808,6 +2808,22 @@ g_execlp3(const char *a1, const char *a2, const char *a3)
28082808
#endif
28092809
}
28102810

2811+
/*****************************************************************************/
2812+
/* does not work in win32 */
2813+
unsigned int
2814+
g_set_alarm(void (*func)(int), unsigned int secs)
2815+
{
2816+
#if defined(_WIN32)
2817+
return 0;
2818+
#else
2819+
/* Cancel any previous alarm to prevent a race */
2820+
unsigned int rv = alarm(0);
2821+
signal(SIGALRM, func);
2822+
(void)alarm(secs);
2823+
return rv;
2824+
#endif
2825+
}
2826+
28112827
/*****************************************************************************/
28122828
/* does not work in win32 */
28132829
void

common/os_calls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ char *g_get_strerror(void);
204204
int g_get_errno(void);
205205
int g_execvp(const char *p1, char *args[]);
206206
int g_execlp3(const char *a1, const char *a2, const char *a3);
207+
unsigned int g_set_alarm(void (*func)(int), unsigned int secs);
207208
void g_signal_child_stop(void (*func)(int));
208209
void g_signal_segfault(void (*func)(int));
209210
void g_signal_hang_up(void (*func)(int));

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ AC_CONFIG_FILES([
575575
instfiles/pulse/Makefile
576576
instfiles/rc.d/Makefile
577577
keygen/Makefile
578+
waitforx/Makefile
578579
libipm/Makefile
579580
libxrdp/Makefile
580581
Makefile

sesman/Makefile.am

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ AM_CPPFLAGS = \
55
-DXRDP_SYSCONF_PATH=\"${sysconfdir}\" \
66
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
77
-DXRDP_SBIN_PATH=\"${sbindir}\" \
8+
-DXRDP_BIN_PATH=\"${bindir}\" \
89
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
910
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
1011
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
@@ -34,7 +35,9 @@ xrdp_sesman_SOURCES = \
3435
sig.c \
3536
sig.h \
3637
xauth.c \
37-
xauth.h
38+
xauth.h \
39+
xwait.c \
40+
xwait.h
3841

3942
# Possible authentication modules
4043
# See https://www.gnu.org/software/automake/manual/html_node/Conditional-Sources.html

sesman/session.c

Lines changed: 2 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "sesman.h"
5050
#include "string_calls.h"
5151
#include "xauth.h"
52+
#include "xwait.h"
5253
#include "xrdp_sockets.h"
5354

5455
#ifndef PR_SET_NO_NEW_PRIVS
@@ -285,42 +286,6 @@ x_server_running_check_ports(int display)
285286
return x_running;
286287
}
287288

288-
/******************************************************************************/
289-
/**
290-
*
291-
* @brief checks if there's a server running on a display
292-
* @param display the display to check
293-
* @return 0 if there isn't a display running, nonzero otherwise
294-
*
295-
*/
296-
static int
297-
x_server_running(int display)
298-
{
299-
char text[256];
300-
int x_running;
301-
302-
g_sprintf(text, "/tmp/.X11-unix/X%d", display);
303-
x_running = g_file_exist(text);
304-
305-
if (!x_running)
306-
{
307-
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
308-
g_sprintf(text, "/tmp/.X%d-lock", display);
309-
x_running = g_file_exist(text);
310-
}
311-
312-
if (x_running)
313-
{
314-
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
315-
}
316-
else
317-
{
318-
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
319-
}
320-
321-
return x_running;
322-
}
323-
324289
/******************************************************************************/
325290
/* called with the main thread
326291
returns boolean */
@@ -375,37 +340,6 @@ session_get_avail_display_from_chain(void)
375340
return 0;
376341
}
377342

378-
/******************************************************************************/
379-
static int
380-
wait_for_xserver(int display)
381-
{
382-
int i;
383-
384-
/* give X a bit to start */
385-
/* wait up to 10 secs for x server to start */
386-
i = 0;
387-
388-
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
389-
390-
while (!x_server_running(display))
391-
{
392-
i++;
393-
394-
if (i > 40)
395-
{
396-
LOG(LOG_LEVEL_WARNING,
397-
"Timed out waiting for X server on display %d to startup",
398-
display);
399-
break;
400-
}
401-
402-
g_sleep(250);
403-
}
404-
405-
return 0;
406-
}
407-
408-
/******************************************************************************/
409343
static int
410344
session_start_chansrv(int uid, int display)
411345
{
@@ -655,13 +589,12 @@ session_start(struct auth_info *auth_info,
655589
}
656590
else if (window_manager_pid == 0)
657591
{
658-
wait_for_xserver(display);
659592
env_set_user(s->uid,
660593
0,
661594
display,
662595
g_cfg->env_names,
663596
g_cfg->env_values);
664-
if (x_server_running(display))
597+
if (wait_for_xserver(display))
665598
{
666599
auth_set_env(auth_info);
667600
if (s->directory != 0)
@@ -912,7 +845,6 @@ session_start(struct auth_info *auth_info,
912845
struct exit_status xserver_exit_status;
913846
struct exit_status chansrv_exit_status;
914847

915-
wait_for_xserver(display);
916848
chansrv_pid = session_start_chansrv(s->uid, display);
917849

918850
LOG(LOG_LEVEL_INFO,

sesman/xwait.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#if defined(HAVE_CONFIG_H)
2+
#include "config_ac.h"
3+
#endif
4+
5+
#include "log.h"
6+
#include "os_calls.h"
7+
#include "string_calls.h"
8+
#include "xwait.h"
9+
10+
#include <stdio.h>
11+
#include <string.h>
12+
13+
/******************************************************************************/
14+
int
15+
wait_for_xserver(int display)
16+
{
17+
FILE *dp = NULL;
18+
int ret = 0;
19+
char buffer[100];
20+
char exe_cmd[262];
21+
22+
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
23+
24+
g_snprintf(exe_cmd, sizeof(exe_cmd), "%s/xrdp-waitforx", XRDP_BIN_PATH);
25+
dp = popen(exe_cmd, "r");
26+
if (dp == NULL)
27+
{
28+
LOG(LOG_LEVEL_ERROR, "Unable to launch xrdp-waitforx");
29+
return 1;
30+
}
31+
32+
while (fgets(buffer, 100, dp))
33+
{
34+
g_strtrim(buffer, 2);
35+
LOG(LOG_LEVEL_DEBUG, "%s", buffer);
36+
}
37+
38+
ret = pclose(dp);
39+
if (ret != 0)
40+
{
41+
LOG(LOG_LEVEL_ERROR, "An error occurred while running xrdp-waitforx");
42+
return 0;
43+
}
44+
45+
46+
return 1;
47+
}

sesman/xwait.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef XWAIT_H
2+
#define XWAIT_H
3+
/**
4+
*
5+
* @brief waits for X to start
6+
* @param display number
7+
* @return 0 on error, 1 if X has outputs
8+
*
9+
*/
10+
int
11+
wait_for_xserver(int display);
12+
#endif

waitforx/Makefile.am

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
bin_PROGRAMS = \
2+
xrdp-waitforx
3+
4+
AM_LDFLAGS = -lX11 -lXrandr
5+
AM_CFLAGS = -I$(top_srcdir)/common
6+
7+
xrdp_waitforx_SOURCES = waitforx.c
8+
9+
xrdp_waitforx_LDADD = \
10+
$(top_builddir)/common/libcommon.la

waitforx/waitforx.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#include <X11/extensions/Xrandr.h>
2+
#include <signal.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <sys/signal.h>
6+
#include <unistd.h>
7+
8+
#include "config_ac.h"
9+
#include "os_calls.h"
10+
#include "string_calls.h"
11+
12+
#define ATTEMPTS 10
13+
#define ALARM_WAIT 30
14+
15+
void
16+
alarm_handler(int signal_num)
17+
{
18+
/* Avoid printf() in signal handler (see signal-safety(7)) */
19+
const char msg[] = "Timed out waiting for RandR outputs\n";
20+
g_file_write(1, msg, g_strlen(msg));
21+
exit(1);
22+
}
23+
24+
int
25+
main(int argc, char **argv)
26+
{
27+
char *display = NULL;
28+
int error_base = 0;
29+
int event_base = 0;
30+
int n = 0;
31+
int outputs = 0;
32+
int wait = ATTEMPTS;
33+
34+
Display *dpy = NULL;
35+
XRRScreenResources *res = NULL;
36+
37+
display = getenv("DISPLAY");
38+
39+
g_set_alarm(alarm_handler, ALARM_WAIT);
40+
41+
if (!display)
42+
{
43+
printf("DISPLAY is null");
44+
exit(1);
45+
}
46+
47+
for (n = 1; n <= wait; ++n)
48+
{
49+
dpy = XOpenDisplay(display);
50+
printf("Opening display %s. Attempt %d of %d\n", display, n, wait);
51+
if (dpy != NULL)
52+
{
53+
printf("Opened display %s\n", display);
54+
break;
55+
}
56+
g_sleep(1000);
57+
}
58+
59+
if (!dpy)
60+
{
61+
printf("Unable to open display %s\n", display);
62+
exit(1);
63+
}
64+
65+
if (!XRRQueryExtension(dpy, &event_base, &error_base))
66+
{
67+
printf("RandR not supported on display %s", display);
68+
}
69+
else
70+
{
71+
for (n = 1; n <= wait; ++n)
72+
{
73+
res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
74+
printf("Waiting for outputs. Attempt %d of %d\n", n, wait);
75+
if (res != NULL)
76+
{
77+
if (res->noutput > 0)
78+
{
79+
outputs = res->noutput;
80+
XRRFreeScreenResources(res);
81+
printf("Found %d output[s]\n", outputs);
82+
break;
83+
}
84+
XRRFreeScreenResources(res);
85+
}
86+
g_sleep(1000);
87+
}
88+
89+
if (outputs > 0)
90+
{
91+
printf("display %s ready with %d outputs\n", display, res->noutput);
92+
}
93+
else
94+
{
95+
printf("Unable to find any outputs\n");
96+
exit(1);
97+
}
98+
}
99+
100+
exit(0);
101+
}

0 commit comments

Comments
 (0)