waitforx logging improvements

This commit is contained in:
matt335672 2023-03-09 10:36:43 +00:00
parent 3681ecdf23
commit 5c01729d6f
5 changed files with 200 additions and 74 deletions

View File

@ -350,9 +350,6 @@ session_start_chansrv(int uid, int display)
chansrv_pid = g_fork(); chansrv_pid = g_fork();
if (chansrv_pid == 0) if (chansrv_pid == 0)
{ {
LOG(LOG_LEVEL_INFO,
"Starting the xrdp channel server for display %d", display);
chansrv_params = list_create(); chansrv_params = list_create();
chansrv_params->auto_free = 1; chansrv_params->auto_free = 1;
@ -364,6 +361,9 @@ session_start_chansrv(int uid, int display)
g_cfg->env_names, g_cfg->env_names,
g_cfg->env_values); g_cfg->env_values);
LOG(LOG_LEVEL_INFO,
"Starting the xrdp channel server for display %d", display);
/* executing chansrv */ /* executing chansrv */
g_execvp_list(exe_path, chansrv_params); g_execvp_list(exe_path, chansrv_params);
@ -585,12 +585,16 @@ session_start(struct auth_info *auth_info,
} }
else if (window_manager_pid == 0) else if (window_manager_pid == 0)
{ {
enum xwait_status xws;
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 (wait_for_xserver(display)) xws = wait_for_xserver(display);
if (xws == XW_STATUS_OK)
{ {
auth_set_env(auth_info); auth_set_env(auth_info);
if (s->directory != 0) if (s->directory != 0)
@ -661,8 +665,18 @@ session_start(struct auth_info *auth_info,
} }
else else
{ {
LOG(LOG_LEVEL_ERROR, switch (xws)
"There is no X server active on display %d", display); {
case XW_STATUS_TIMED_OUT:
LOG(LOG_LEVEL_ERROR, "Timed out waiting for X server");
break;
case XW_STATUS_FAILED_TO_START:
LOG(LOG_LEVEL_ERROR, "X server failed to start");
break;
default:
LOG(LOG_LEVEL_ERROR,
"An error occurred waiting for the X server");
}
} }
LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting to start " LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting to start "

View File

@ -9,39 +9,82 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/wait.h>
/******************************************************************************/ /******************************************************************************/
int enum xwait_status
wait_for_xserver(int display) wait_for_xserver(int display)
{ {
FILE *dp = NULL; FILE *dp = NULL;
int ret = 0; enum xwait_status rv = XW_STATUS_MISC_ERROR;
int ret;
char buffer[100]; char buffer[100];
char exe_cmd[262]; const char exe[] = XRDP_LIBEXEC_PATH "/waitforx";
char cmd[sizeof(exe) + 64];
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display); if (!g_file_exist(exe))
{
LOG(LOG_LEVEL_ERROR, "Unable to find %s", exe);
return rv;
}
g_snprintf(exe_cmd, sizeof(exe_cmd), "%s/waitforx", XRDP_LIBEXEC_PATH); g_snprintf(cmd, sizeof(cmd), "%s -d :%d", exe, display);
dp = popen(exe_cmd, "r"); LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display :%d",
display);
dp = popen(cmd, "r");
if (dp == NULL) if (dp == NULL)
{ {
LOG(LOG_LEVEL_ERROR, "Unable to launch waitforx"); LOG(LOG_LEVEL_ERROR, "Unable to launch waitforx");
return 1; return rv;
} }
while (fgets(buffer, 100, dp)) while (fgets(buffer, 100, dp))
{ {
const char *msg = buffer;
enum logLevels level = LOG_LEVEL_ERROR;
g_strtrim(buffer, 2); g_strtrim(buffer, 2);
LOG(LOG_LEVEL_DEBUG, "%s", buffer);
// Has the message got a class at the start?
if (strlen(buffer) > 3 && buffer[0] == '<' && buffer[2] == '>')
{
switch (buffer[1])
{
case 'D':
level = LOG_LEVEL_DEBUG;
break;
case 'I':
level = LOG_LEVEL_INFO;
break;
case 'W':
level = LOG_LEVEL_WARNING;
break;
default:
level = LOG_LEVEL_ERROR;
break;
}
msg = buffer + 3;
}
if (strlen(msg) > 0)
{
LOG(level, "waitforx: %s", msg);
}
} }
ret = pclose(dp); ret = pclose(dp);
if (ret != 0) if (WIFEXITED(ret))
{ {
LOG(LOG_LEVEL_ERROR, "An error occurred while running waitforx"); rv = (enum xwait_status)WEXITSTATUS(ret);
return 0; }
else if (WIFSIGNALED(ret))
{
int sig = WTERMSIG(ret);
LOG(LOG_LEVEL_ERROR, "waitforx failed with unexpected signal %d",
sig);
} }
return rv;
return 1;
} }

View File

@ -1,12 +1,21 @@
#ifndef XWAIT_H #ifndef XWAIT_H
#define XWAIT_H #define XWAIT_H
enum xwait_status
{
XW_STATUS_OK = 0,
XW_STATUS_MISC_ERROR,
XW_STATUS_TIMED_OUT,
XW_STATUS_FAILED_TO_START
};
/** /**
* *
* @brief waits for X to start * @brief waits for X to start
* @param display number * @param display number
* @return 0 on error, 1 if X has outputs * @return status
* *
*/ */
int enum xwait_status
wait_for_xserver(int display); wait_for_xserver(int display);
#endif #endif

View File

@ -3,7 +3,9 @@ pkglibexec_PROGRAMS = \
AM_LDFLAGS = -lX11 -lXrandr AM_LDFLAGS = -lX11 -lXrandr
AM_CPPFLAGS = -I$(top_srcdir)/common AM_CPPFLAGS = \
-I$(top_srcdir)/sesman \
-I$(top_srcdir)/common
AM_CFLAGS = $(X_CFLAGS) AM_CFLAGS = $(X_CFLAGS)

View File

@ -8,94 +8,152 @@
#include "config_ac.h" #include "config_ac.h"
#include "os_calls.h" #include "os_calls.h"
#include "string_calls.h" #include "string_calls.h"
#include "xwait.h" // For return status codes
#define ATTEMPTS 10 #define ATTEMPTS 10
#define ALARM_WAIT 30 #define ALARM_WAIT 30
void /*****************************************************************************/
static void
alarm_handler(int signal_num) alarm_handler(int signal_num)
{ {
/* Avoid printf() in signal handler (see signal-safety(7)) */ /* Avoid printf() in signal handler (see signal-safety(7))
const char msg[] = "Timed out waiting for RandR outputs\n"; *
* Prefix the message with a newline in case another message
* has been partly output */
const char msg[] = "\n<E>Timed out waiting for RandR outputs\n";
g_file_write(1, msg, g_strlen(msg)); g_file_write(1, msg, g_strlen(msg));
exit(1); exit(XW_STATUS_TIMED_OUT);
} }
int /*****************************************************************************/
main(int argc, char **argv) static Display *
open_display(const char *display)
{ {
char *display = NULL;
int error_base = 0;
int event_base = 0;
int n = 0;
int outputs = 0;
int wait = ATTEMPTS;
Display *dpy = NULL; Display *dpy = NULL;
XRRScreenResources *res = NULL; unsigned int wait = ATTEMPTS;
unsigned int n;
display = getenv("DISPLAY"); for (n = 1; n <= ATTEMPTS; ++n)
g_set_alarm(alarm_handler, ALARM_WAIT);
if (!display)
{
printf("DISPLAY is null");
exit(1);
}
for (n = 1; n <= wait; ++n)
{ {
printf("<D>Opening display %s. Attempt %u of %u\n", display, n, wait);
dpy = XOpenDisplay(display); dpy = XOpenDisplay(display);
printf("Opening display %s. Attempt %d of %d\n", display, n, wait);
if (dpy != NULL) if (dpy != NULL)
{ {
printf("Opened display %s\n", display); printf("<D>Opened display %s\n", display);
break; break;
} }
g_sleep(1000); g_sleep(1000);
} }
if (!dpy) return dpy;
{ }
printf("Unable to open display %s\n", display);
exit(1); /*****************************************************************************/
} /**
* Wait for the RandR extension (if in use) to be available
*
* @param dpy Display
* @return 0 if/when outputs are available, 1 otherwise
*/
static int
wait_for_r_and_r(Display *dpy)
{
int error_base = 0;
int event_base = 0;
unsigned int outputs = 0;
unsigned int wait = ATTEMPTS;
unsigned int n;
XRRScreenResources *res = NULL;
if (!XRRQueryExtension(dpy, &event_base, &error_base)) if (!XRRQueryExtension(dpy, &event_base, &error_base))
{ {
printf("RandR not supported on display %s", display); printf("<I>RandR not supported on display %s\n",
DisplayString(dpy));
return 0;
} }
else
for (n = 1; n <= wait; ++n)
{ {
for (n = 1; n <= wait; ++n) printf("<D>Waiting for outputs. Attempt %u of %u\n", n, wait);
res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
if (res != NULL)
{ {
res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy)); if (res->noutput > 0)
printf("Waiting for outputs. Attempt %d of %d\n", n, wait);
if (res != NULL)
{ {
if (res->noutput > 0) outputs = res->noutput;
{
outputs = res->noutput;
XRRFreeScreenResources(res);
printf("Found %d output[s]\n", outputs);
break;
}
XRRFreeScreenResources(res);
} }
g_sleep(1000); XRRFreeScreenResources(res);
} }
if (outputs > 0) if (outputs > 0)
{ {
printf("display %s ready with %d outputs\n", display, res->noutput); printf("<D>Display %s ready with %u RandR outputs\n",
DisplayString(dpy), outputs);
return 0;
} }
else g_sleep(1000);
}
printf("<E>Unable to find any RandR outputs\n");
return 1;
}
/*****************************************************************************/
static void
usage(const char *argv0, int status)
{
printf("Usage: %s -d display\n", argv0);
exit(status);
}
/*****************************************************************************/
int
main(int argc, char **argv)
{
const char *display_name = NULL;
int opt;
int status = XW_STATUS_MISC_ERROR;
Display *dpy = NULL;
/* Disable stdout buffering so any messages are passed immediately
* to sesman */
setvbuf(stdout, NULL, _IONBF, 0);
while ((opt = getopt(argc, argv, "d:")) != -1)
{
switch (opt)
{ {
printf("Unable to find any outputs\n"); case 'd':
exit(1); display_name = optarg;
break;
default: /* '?' */
usage(argv[0], status);
} }
} }
exit(0); if (!display_name)
{
usage(argv[0], status);
}
g_set_alarm(alarm_handler, ALARM_WAIT);
dpy = open_display(display_name);
if (!dpy)
{
printf("<E>Unable to open display %s\n", display_name);
status = XW_STATUS_FAILED_TO_START;
}
else
{
if (wait_for_r_and_r(dpy) == 0)
{
status = XW_STATUS_OK;
}
XCloseDisplay(dpy);
}
return status;
} }