@@ -1558,9 +1558,16 @@ static void wait_for_unix_socket(Ghandles *g)
15581558
15591559 addrlen = sizeof (peer );
15601560 fprintf (stderr , "Waiting on %s socket...\n" , SOCKET_ADDRESS );
1561+ if (g -> x_pid == (pid_t )- 1 ) {
1562+ fprintf (stderr , "Xorg exited in the meantime, aborting\n" );
1563+ exit (1 );
1564+ }
15611565 g -> xserver_fd = accept (g -> xserver_listen_fd , (struct sockaddr * ) & peer , & addrlen );
15621566 if (g -> xserver_fd == -1 ) {
1563- perror ("unix accept" );
1567+ if (errno == EINTR && g -> x_pid == (pid_t )- 1 )
1568+ fprintf (stderr , "Xorg exited in the meantime, aborting\n" );
1569+ else
1570+ perror ("unix accept" );
15641571 exit (1 );
15651572 }
15661573 fprintf (stderr , "Ok, somebody connected.\n" );
@@ -2317,6 +2324,21 @@ static _Noreturn void handle_sigterm(int UNUSED(sig),
23172324 exit (0 );
23182325}
23192326
2327+ static void handle_sigchld (int UNUSED (sig ),
2328+ siginfo_t * UNUSED (info ), void * UNUSED (context ))
2329+ {
2330+ Ghandles * g = ghandles_for_vchan_reinitialize ;
2331+ if (g -> x_pid != (pid_t )- 1 ) {
2332+ int status ;
2333+ pid_t pid = waitpid (g -> x_pid , & status , WNOHANG );
2334+ if (pid == g -> x_pid && (WIFEXITED (status ) || WIFSIGNALED (status )))
2335+ /* TODO: consider saving also exit status, but right now gui-agent
2336+ * would handle it the same regardless, so maybe later, just for
2337+ * logging purposes */
2338+ g -> x_pid = -1 ;
2339+ }
2340+ }
2341+
23202342static void usage (void )
23212343{
23222344 fprintf (stderr , "Usage: qubes_gui [options]\n" );
@@ -2380,7 +2402,7 @@ int main(int argc, char **argv)
23802402{
23812403 int i ;
23822404 int xfd ;
2383- Ghandles g ;
2405+ Ghandles g = { . x_pid = -1 } ;
23842406
23852407 g .created_input_device = access ("/run/qubes-service/gui-agent-virtual-input-device" , F_OK ) == 0 ;
23862408
@@ -2454,10 +2476,27 @@ int main(int argc, char **argv)
24542476 libvchan_wait (g .vchan );
24552477 saved_argv = argv ;
24562478 vchan_register_at_eof (handle_guid_disconnect );
2479+
2480+ ghandles_for_vchan_reinitialize = & g ;
2481+ struct sigaction sigchld_handler = {
2482+ .sa_sigaction = handle_sigchld ,
2483+ .sa_flags = SA_SIGINFO ,
2484+ };
2485+ sigemptyset (& sigchld_handler .sa_mask );
2486+ if (sigaction (SIGCHLD , & sigchld_handler , NULL ))
2487+ err (1 , "sigaction" );
2488+ struct sigaction sigterm_handler = {
2489+ .sa_sigaction = handle_sigterm ,
2490+ .sa_flags = SA_SIGINFO ,
2491+ };
2492+ sigemptyset (& sigterm_handler .sa_mask );
2493+ if (sigaction (SIGTERM , & sigterm_handler , NULL ))
2494+ err (1 , "sigaction" );
2495+
24572496 handshake (& g );
24582497 g .x_pid = get_xconf_and_run_x (& g );
2498+
24592499 mkghandles (& g );
2460- ghandles_for_vchan_reinitialize = & g ;
24612500 /* Turn on Composite for all children of root window. This way X server
24622501 * keeps separate buffers for each (root child) window.
24632502 * There are two modes:
@@ -2497,14 +2536,6 @@ int main(int argc, char **argv)
24972536 fprintf (stderr , "XFixes not available, cursor shape handling off\n" );
24982537
24992538 XAutoRepeatOff (g .display );
2500- signal (SIGCHLD , SIG_IGN );
2501- struct sigaction sigterm_handler = {
2502- .sa_sigaction = handle_sigterm ,
2503- .sa_flags = SA_SIGINFO ,
2504- };
2505- sigemptyset (& sigterm_handler .sa_mask );
2506- if (sigaction (SIGTERM , & sigterm_handler , NULL ))
2507- err (1 , "sigaction" );
25082539 windows_list = list_new ();
25092540 embeder_list = list_new ();
25102541 XSetErrorHandler (dummy_handler );
@@ -2541,6 +2572,11 @@ int main(int argc, char **argv)
25412572 for (;;) {
25422573 int busy ;
25432574
2575+ if (g .x_pid == -1 ) {
2576+ fprintf (stderr , "Xorg exited prematurely\n" );
2577+ exit (1 );
2578+ }
2579+
25442580 fds [0 ].fd = libvchan_fd_for_select (g .vchan );
25452581 wait_for_vchan_or_argfd (g .vchan , fds , QUBES_ARRAY_SIZE (fds ));
25462582 /* first process possible qubes_drv reconnection, otherwise we may be
0 commit comments