mirror of https://github.com/neutrinolabs/xrdp
os_calls changes
- Add g_pipe() - Add g_file_duplicate_on() - Rework struct exit_status to make it easier to parse - Add optional status return to g_waitchild()
This commit is contained in:
parent
b53060e734
commit
8b9f9b40c8
|
@ -1396,6 +1396,13 @@ g_sleep(int msecs)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
g_pipe(int fd[2])
|
||||
{
|
||||
return pipe(fd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
g_sck_last_error_would_block(int sck)
|
||||
|
@ -2344,6 +2351,24 @@ mode_t_to_hex(mode_t mode)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Duplicates a file descriptor onto another one using the semantics
|
||||
* of dup2() */
|
||||
/* return boolean */
|
||||
int
|
||||
g_file_duplicate_on(int fd, int target_fd)
|
||||
{
|
||||
int rv = (dup2(fd, target_fd) >= 0);
|
||||
|
||||
if (rv < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't clone file %d as file %d [%s]",
|
||||
fd, target_fd, g_get_strerror());
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int
|
||||
|
@ -3051,9 +3076,11 @@ g_set_allusercontext(int uid)
|
|||
#endif
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32
|
||||
returns pid of process that exits or zero if signal occurred */
|
||||
returns pid of process that exits or zero if signal occurred
|
||||
an exit_status struct can optionally be passed in to get the
|
||||
exit status of the child */
|
||||
int
|
||||
g_waitchild(void)
|
||||
g_waitchild(struct exit_status *e)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return 0;
|
||||
|
@ -3061,15 +3088,36 @@ g_waitchild(void)
|
|||
int wstat;
|
||||
int rv;
|
||||
|
||||
struct exit_status dummy;
|
||||
|
||||
if (e == NULL)
|
||||
{
|
||||
e = &dummy; // Set this, then throw it away
|
||||
}
|
||||
|
||||
e->reason = E_XR_UNEXPECTED;
|
||||
e->val = 0;
|
||||
|
||||
rv = waitpid(0, &wstat, WNOHANG);
|
||||
|
||||
if (rv == -1)
|
||||
{
|
||||
if (errno == EINTR) /* signal occurred */
|
||||
if (errno == EINTR)
|
||||
{
|
||||
/* This shouldn't happen as signal handlers use SA_RESTART */
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
else if (WIFEXITED(wstat))
|
||||
{
|
||||
e->reason = E_XR_STATUS_CODE;
|
||||
e->val = WEXITSTATUS(wstat);
|
||||
}
|
||||
else if (WIFSIGNALED(wstat))
|
||||
{
|
||||
e->reason = E_XR_SIGNAL;
|
||||
e->val = WTERMSIG(wstat);
|
||||
}
|
||||
|
||||
return rv;
|
||||
#endif
|
||||
|
@ -3077,7 +3125,10 @@ g_waitchild(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32
|
||||
returns pid of process that exits or <= 0 if no process was found */
|
||||
returns pid of process that exits or <= 0 if no process was found
|
||||
|
||||
Note that signal handlers are established with BSD-style semantics,
|
||||
so this call is NOT interrupted by a signal */
|
||||
int
|
||||
g_waitpid(int pid)
|
||||
{
|
||||
|
@ -3101,25 +3152,21 @@ g_waitpid(int pid)
|
|||
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32
|
||||
returns exit status code of child process with pid */
|
||||
returns exit status code of child process with pid
|
||||
|
||||
Note that signal handlers are established with BSD-style semantics,
|
||||
so this call is NOT interrupted by a signal */
|
||||
struct exit_status
|
||||
g_waitpid_status(int pid)
|
||||
{
|
||||
struct exit_status exit_status;
|
||||
|
||||
#if defined(_WIN32)
|
||||
exit_status.exit_code = -1;
|
||||
exit_status.signal_no = 0;
|
||||
return exit_status;
|
||||
#else
|
||||
int rv;
|
||||
int status;
|
||||
|
||||
exit_status.exit_code = -1;
|
||||
exit_status.signal_no = 0;
|
||||
struct exit_status exit_status = {.reason = E_XR_UNEXPECTED, .val = 0};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
if (pid > 0)
|
||||
{
|
||||
int rv;
|
||||
int status;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "waiting for pid %d to exit", pid);
|
||||
rv = waitpid(pid, &status, 0);
|
||||
|
||||
|
@ -3127,11 +3174,13 @@ g_waitpid_status(int pid)
|
|||
{
|
||||
if (WIFEXITED(status))
|
||||
{
|
||||
exit_status.exit_code = WEXITSTATUS(status);
|
||||
exit_status.reason = E_XR_STATUS_CODE;
|
||||
exit_status.val = WEXITSTATUS(status);
|
||||
}
|
||||
if (WIFSIGNALED(status))
|
||||
{
|
||||
exit_status.signal_no = WTERMSIG(status);
|
||||
exit_status.reason = E_XR_SIGNAL;
|
||||
exit_status.val = WTERMSIG(status);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -3140,8 +3189,8 @@ g_waitpid_status(int pid)
|
|||
}
|
||||
}
|
||||
|
||||
return exit_status;
|
||||
#endif
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -23,13 +23,17 @@
|
|||
|
||||
#include "arch.h"
|
||||
|
||||
enum exit_reason
|
||||
{
|
||||
E_XR_STATUS_CODE = 0, ///< 'val' contains exit status
|
||||
E_XR_SIGNAL, ///< 'val' contains a signal number
|
||||
E_XR_UNEXPECTED
|
||||
};
|
||||
|
||||
struct exit_status
|
||||
{
|
||||
/* set to -1 when the process exited via a signal */
|
||||
uint8_t exit_code;
|
||||
|
||||
/* set to 0 when the process exited normally */
|
||||
uint8_t signal_no;
|
||||
enum exit_reason reason;
|
||||
int val;
|
||||
};
|
||||
|
||||
struct list;
|
||||
|
@ -178,6 +182,8 @@ const char *
|
|||
g_sck_get_peer_description(int sck,
|
||||
char *desc, unsigned int bytes);
|
||||
void g_sleep(int msecs);
|
||||
int g_pipe(int fd[2]);
|
||||
|
||||
tintptr g_create_wait_obj(const char *name);
|
||||
tintptr g_create_wait_obj_from_socket(tintptr socket, int write);
|
||||
void g_delete_wait_obj_from_socket(tintptr wait_obj);
|
||||
|
@ -213,6 +219,7 @@ int g_file_read(int fd, char *ptr, int len);
|
|||
int g_file_write(int fd, const char *ptr, int len);
|
||||
int g_file_seek(int fd, int offset);
|
||||
int g_file_lock(int fd, int start, int len);
|
||||
int g_file_duplicate_on(int fd, int target_fd);
|
||||
int g_chmod_hex(const char *filename, int flags);
|
||||
int g_umask_hex(int flags);
|
||||
int g_chown(const char *name, int uid, int gid);
|
||||
|
@ -273,7 +280,7 @@ int g_setlogin(const char *name);
|
|||
*/
|
||||
int g_set_allusercontext(int uid);
|
||||
#endif
|
||||
int g_waitchild(void);
|
||||
int g_waitchild(struct exit_status *e);
|
||||
int g_waitpid(int pid);
|
||||
struct exit_status g_waitpid_status(int pid);
|
||||
void g_clearenv(void);
|
||||
|
|
|
@ -1522,7 +1522,7 @@ child_signal_handler(int sig)
|
|||
LOG_DEVEL(LOG_LEVEL_INFO, "child_signal_handler:");
|
||||
do
|
||||
{
|
||||
pid = g_waitchild();
|
||||
pid = g_waitchild(NULL);
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "child_signal_handler: child pid %d", pid);
|
||||
if ((pid == g_exec_pid) && (pid > 0))
|
||||
{
|
||||
|
|
|
@ -401,6 +401,33 @@ username_from_uid(int uid, char *uname, int uname_len)
|
|||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static void
|
||||
exit_status_to_str(const struct exit_status *e, char buff[], int bufflen)
|
||||
{
|
||||
switch (e->reason)
|
||||
{
|
||||
case E_XR_STATUS_CODE:
|
||||
if (e->val == 0)
|
||||
{
|
||||
g_snprintf(buff, bufflen, "exit code zero");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(buff, bufflen, "non-zero exit code %d", e->val);
|
||||
}
|
||||
break;
|
||||
|
||||
case E_XR_SIGNAL:
|
||||
g_snprintf(buff, bufflen, "signal %d", e->val);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_snprintf(buff, bufflen, "an unexpected error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
enum scp_screate_status
|
||||
|
@ -841,7 +868,7 @@ session_start(struct auth_info *auth_info,
|
|||
struct exit_status wm_exit_status;
|
||||
struct exit_status xserver_exit_status;
|
||||
struct exit_status chansrv_exit_status;
|
||||
|
||||
char reason[128];
|
||||
chansrv_pid = session_start_chansrv(s->uid, display);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
|
@ -857,13 +884,20 @@ session_start(struct auth_info *auth_info,
|
|||
wm_wait_time = g_time1();
|
||||
wm_exit_status = g_waitpid_status(window_manager_pid);
|
||||
wm_wait_time = g_time1() - wm_wait_time;
|
||||
if (wm_exit_status.exit_code > 0)
|
||||
if (wm_exit_status.reason == E_XR_STATUS_CODE &&
|
||||
wm_exit_status.val == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
|
||||
"exited with non-zero exit code %d and signal %d. This "
|
||||
// Normal exit
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_status_to_str(&wm_exit_status, reason, sizeof(reason));
|
||||
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Window manager (pid %d, display %d) "
|
||||
"exited with %s. This "
|
||||
"could indicate a window manager config problem",
|
||||
window_manager_pid, display, wm_exit_status.exit_code,
|
||||
wm_exit_status.signal_no);
|
||||
window_manager_pid, display, reason);
|
||||
}
|
||||
if (wm_wait_time < 10)
|
||||
{
|
||||
|
@ -898,18 +932,17 @@ session_start(struct auth_info *auth_info,
|
|||
|
||||
/* make sure socket cleanup happen after child process exit */
|
||||
xserver_exit_status = g_waitpid_status(display_pid);
|
||||
exit_status_to_str(&xserver_exit_status, reason, sizeof(reason));
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"X server on display %d (pid %d) returned exit code %d "
|
||||
"and signal number %d",
|
||||
display, display_pid, xserver_exit_status.exit_code,
|
||||
xserver_exit_status.signal_no);
|
||||
"X server on display %d (pid %d) exited with %s",
|
||||
display, display_pid, reason);
|
||||
|
||||
chansrv_exit_status = g_waitpid_status(chansrv_pid);
|
||||
exit_status_to_str(&chansrv_exit_status, reason, sizeof(reason));
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"xrdp channel server for display %d (pid %d) "
|
||||
"exit code %d and signal number %d",
|
||||
display, chansrv_pid, chansrv_exit_status.exit_code,
|
||||
chansrv_exit_status.signal_no);
|
||||
"xrdp channel server for display %d (pid %d)"
|
||||
" exited with %s",
|
||||
display, chansrv_pid, reason);
|
||||
|
||||
cleanup_sockets(display);
|
||||
g_deinit();
|
||||
|
|
|
@ -105,7 +105,7 @@ sig_sesman_session_end(void)
|
|||
LOG(LOG_LEVEL_DEBUG, "receiving SIGCHLD");
|
||||
do
|
||||
{
|
||||
pid = g_waitchild();
|
||||
pid = g_waitchild(NULL);
|
||||
|
||||
if (pid > 0)
|
||||
{
|
||||
|
|
|
@ -89,7 +89,7 @@ xrdp_shutdown(int sig)
|
|||
static void
|
||||
xrdp_child(int sig)
|
||||
{
|
||||
while (g_waitchild() > 0)
|
||||
while (g_waitchild(NULL) > 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue