21
21
22
22
#include <glib.h>
23
23
#include <unistd.h>
24
+ #include <signal.h>
25
+
26
+ #include <sys/types.h>
27
+ #include <sys/wait.h>
28
+ #include <sys/prctl.h>
24
29
25
30
#include <crm/crm.h>
26
31
#include <crm/msg_xml.h>
@@ -391,6 +396,119 @@ void handle_shutdown_nack()
391
396
crm_debug ("Ignoring unexpected shutdown nack" );
392
397
}
393
398
399
+
400
+ static pid_t main_pid = 0 ;
401
+ static void
402
+ sigdone (void )
403
+ {
404
+ exit (0 );
405
+ }
406
+
407
+ static void
408
+ sigreap (void )
409
+ {
410
+ pid_t pid = 0 ;
411
+ int status ;
412
+ do {
413
+ /*
414
+ * Opinions seem to differ as to what to put here:
415
+ * -1, any child process
416
+ * 0, any child process whose process group ID is equal to that of the calling process
417
+ */
418
+ pid = waitpid (-1 , & status , WNOHANG );
419
+ if (pid == main_pid ) {
420
+ /* Exit when pacemaker-remote exits and use the same return code */
421
+ if (WIFEXITED (status )) {
422
+ exit (WEXITSTATUS (status ));
423
+ }
424
+ exit (1 );
425
+ }
426
+
427
+ } while (pid > 0 );
428
+ }
429
+
430
+ static struct {
431
+ int sig ;
432
+ void (* handler )(void );
433
+ } sigmap [] = {
434
+ { SIGCHLD , sigreap },
435
+ { SIGINT , sigdone },
436
+ };
437
+
438
+ static void spawn_pidone (int argc , char * * argv , char * * envp )
439
+ {
440
+ sigset_t set ;
441
+
442
+ if (getpid () != 1 ) {
443
+ return ;
444
+ }
445
+
446
+ sigfillset (& set );
447
+ sigprocmask (SIG_BLOCK , & set , 0 );
448
+
449
+ main_pid = fork ();
450
+ switch (main_pid ) {
451
+ case 0 :
452
+ sigprocmask (SIG_UNBLOCK , & set , NULL );
453
+ setsid ();
454
+ setpgid (0 , 0 );
455
+
456
+ /* Child remains as pacemaker_remoted */
457
+ return ;
458
+ case -1 :
459
+ perror ("fork" );
460
+ }
461
+
462
+ /* Parent becomes the reaper of zombie processes */
463
+ /* Safe to initialize logging now if needed */
464
+
465
+ #ifdef HAVE___PROGNAME
466
+ /* Differentiate ourselves in the 'ps' output */
467
+ {
468
+ char * p ;
469
+ int i , maxlen ;
470
+ char * LastArgv = NULL ;
471
+ const char * name = "pcmk-init" ;
472
+
473
+ for (i = 0 ; i < argc ; i ++ ) {
474
+ if (!i || (LastArgv + 1 == argv [i ]))
475
+ LastArgv = argv [i ] + strlen (argv [i ]);
476
+ }
477
+
478
+ for (i = 0 ; envp [i ] != NULL ; i ++ ) {
479
+ if ((LastArgv + 1 ) == envp [i ]) {
480
+ LastArgv = envp [i ] + strlen (envp [i ]);
481
+ }
482
+ }
483
+
484
+ maxlen = (LastArgv - argv [0 ]) - 2 ;
485
+
486
+ i = strlen (name );
487
+ /* We can overwrite individual argv[] arguments */
488
+ snprintf (argv [0 ], maxlen , "%s" , name );
489
+
490
+ /* Now zero out everything else */
491
+ p = & argv [0 ][i ];
492
+ while (p < LastArgv )
493
+ * p ++ = '\0' ;
494
+ argv [1 ] = NULL ;
495
+ }
496
+ #endif /* HAVE___PROGNAME */
497
+
498
+ while (1 ) {
499
+ int sig ;
500
+ size_t i ;
501
+
502
+ sigwait (& set , & sig );
503
+ for (i = 0 ; i < DIMOF (sigmap ); i ++ ) {
504
+ if (sigmap [i ].sig == sig ) {
505
+ sigmap [i ].handler ();
506
+ break ;
507
+ }
508
+ }
509
+ }
510
+ }
511
+
394
512
/* *INDENT-OFF* */
395
513
static struct crm_option long_options [] = {
396
514
/* Top-level Options */
@@ -410,12 +528,14 @@ static struct crm_option long_options[] = {
410
528
/* *INDENT-ON* */
411
529
412
530
int
413
- main (int argc , char * * argv )
531
+ main (int argc , char * * argv , char * * envp )
414
532
{
415
533
int flag = 0 ;
416
534
int index = 0 ;
417
535
const char * option = NULL ;
418
536
537
+ /* If necessary, create PID1 now before any FDs are opened */
538
+ spawn_pidone (argc , argv , envp );
419
539
420
540
#ifndef ENABLE_PCMK_REMOTE
421
541
crm_log_preinit ("lrmd" , argc , argv );
0 commit comments