@@ -1558,9 +1558,16 @@ static void wait_for_unix_socket(Ghandles *g)
1558
1558
1559
1559
addrlen = sizeof (peer );
1560
1560
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
+ }
1561
1565
g -> xserver_fd = accept (g -> xserver_listen_fd , (struct sockaddr * ) & peer , & addrlen );
1562
1566
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" );
1564
1571
exit (1 );
1565
1572
}
1566
1573
fprintf (stderr , "Ok, somebody connected.\n" );
@@ -2317,6 +2324,21 @@ static _Noreturn void handle_sigterm(int UNUSED(sig),
2317
2324
exit (0 );
2318
2325
}
2319
2326
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
+
2320
2342
static void usage (void )
2321
2343
{
2322
2344
fprintf (stderr , "Usage: qubes_gui [options]\n" );
@@ -2380,7 +2402,7 @@ int main(int argc, char **argv)
2380
2402
{
2381
2403
int i ;
2382
2404
int xfd ;
2383
- Ghandles g ;
2405
+ Ghandles g = { . x_pid = -1 } ;
2384
2406
2385
2407
g .created_input_device = access ("/run/qubes-service/gui-agent-virtual-input-device" , F_OK ) == 0 ;
2386
2408
@@ -2454,10 +2476,27 @@ int main(int argc, char **argv)
2454
2476
libvchan_wait (g .vchan );
2455
2477
saved_argv = argv ;
2456
2478
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
+
2457
2496
handshake (& g );
2458
2497
g .x_pid = get_xconf_and_run_x (& g );
2498
+
2459
2499
mkghandles (& g );
2460
- ghandles_for_vchan_reinitialize = & g ;
2461
2500
/* Turn on Composite for all children of root window. This way X server
2462
2501
* keeps separate buffers for each (root child) window.
2463
2502
* There are two modes:
@@ -2497,14 +2536,6 @@ int main(int argc, char **argv)
2497
2536
fprintf (stderr , "XFixes not available, cursor shape handling off\n" );
2498
2537
2499
2538
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" );
2508
2539
windows_list = list_new ();
2509
2540
embeder_list = list_new ();
2510
2541
XSetErrorHandler (dummy_handler );
@@ -2541,6 +2572,11 @@ int main(int argc, char **argv)
2541
2572
for (;;) {
2542
2573
int busy ;
2543
2574
2575
+ if (g .x_pid == -1 ) {
2576
+ fprintf (stderr , "Xorg exited prematurely\n" );
2577
+ exit (1 );
2578
+ }
2579
+
2544
2580
fds [0 ].fd = libvchan_fd_for_select (g .vchan );
2545
2581
wait_for_vchan_or_argfd (g .vchan , fds , QUBES_ARRAY_SIZE (fds ));
2546
2582
/* first process possible qubes_drv reconnection, otherwise we may be
0 commit comments