(root)/
glibc-2.38/
posix/
tst-spawn7.c
       1  /* Tests for posix_spawn signal handling.
       2     Copyright (C) 2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <http://www.gnu.org/licenses/>.  */
      18  
      19  #include <assert.h>
      20  #include <getopt.h>
      21  #include <spawn.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <support/check.h>
      25  #include <support/xsignal.h>
      26  #include <support/xunistd.h>
      27  #include <unistd.h>
      28  
      29  /* Nonzero if the program gets called via `exec'.  */
      30  #define CMDLINE_OPTIONS \
      31    { "restart", no_argument, &restart, 1 },
      32  static int restart;
      33  
      34  /* Hold the four initial argument used to respawn the process, plus the extra
      35     '--direct', '--restart', the check type ('SIG_IGN' or 'SIG_DFL'), and a
      36     final NULL.  */
      37  static char *spargs[8];
      38  static int check_type_argc;
      39  
      40  /* Called on process re-execution.  */
      41  _Noreturn static void
      42  handle_restart (int argc, char *argv[])
      43  {
      44    assert (argc == 1);
      45  
      46    if (strcmp (argv[0], "SIG_DFL") == 0)
      47      {
      48        for (int i = 1; i < NSIG; i++)
      49  	{
      50  	  struct sigaction sa;
      51  	  int r = sigaction (i, NULL, &sa);
      52  	  /* Skip internal signals (such as SIGCANCEL).  */
      53  	  if (r == -1)
      54  	    continue;
      55  	  TEST_VERIFY_EXIT (sa.sa_handler == SIG_DFL);
      56  	}
      57        exit (EXIT_SUCCESS);
      58      }
      59    else if (strcmp (argv[0], "SIG_IGN") == 0)
      60      {
      61        for (int i = 1; i < NSIG; i++)
      62  	{
      63  	  struct sigaction sa;
      64  	  int r = sigaction (i, NULL, &sa);
      65  	  /* Skip internal signals (such as SIGCANCEL).  */
      66  	  if (r == -1)
      67  	    continue;
      68  	  if (i == SIGUSR1 || i == SIGUSR2)
      69  	    TEST_VERIFY_EXIT (sa.sa_handler == SIG_IGN);
      70  	  else
      71  	    TEST_VERIFY_EXIT (sa.sa_handler == SIG_DFL);
      72  	}
      73        exit (EXIT_SUCCESS);
      74      }
      75  
      76    exit (EXIT_FAILURE);
      77  }
      78  
      79  static void
      80  spawn_signal_test (const char *type, const posix_spawnattr_t *attr)
      81  {
      82    spargs[check_type_argc] = (char*) type;
      83  
      84    pid_t pid;
      85    int status;
      86  
      87    TEST_COMPARE (posix_spawn (&pid, spargs[0], NULL, attr, spargs, environ), 0);
      88    TEST_COMPARE (xwaitpid (pid, &status, 0), pid);
      89    TEST_VERIFY (WIFEXITED (status));
      90    TEST_VERIFY (!WIFSIGNALED (status));
      91    TEST_COMPARE (WEXITSTATUS (status), 0);
      92  }
      93  
      94  static void
      95  dummy_sa_handler (int signal)
      96  {
      97  }
      98  
      99  static void
     100  do_test_signals (void)
     101  {
     102    /* Ensure the initial signal disposition, ignore EINVAL for internal
     103       signal such as SIGCANCEL.  */
     104    for (int sig = 1; sig < _NSIG; ++sig)
     105      sigaction (sig, &(struct sigaction) { .sa_handler = SIG_DFL,
     106  					  .sa_flags = 0 }, NULL);
     107  
     108    {
     109      /* Check if all signals handler are set to SIG_DFL on spawned process.  */
     110      spawn_signal_test ("SIG_DFL", NULL);
     111    }
     112  
     113    {
     114      /* Same as before, but set SIGUSR1 and SIGUSR2 to a handler different than
     115         SIG_IGN or SIG_DFL.  */
     116      struct sigaction sa = { 0 };
     117      sa.sa_handler = dummy_sa_handler;
     118      xsigaction (SIGUSR1, &sa, NULL);
     119      xsigaction (SIGUSR2, &sa, NULL);
     120      spawn_signal_test ("SIG_DFL", NULL);
     121    }
     122  
     123    {
     124      /* Check if SIG_IGN is keep as is.  */
     125      struct sigaction sa = { 0 };
     126      sa.sa_handler = SIG_IGN;
     127      xsigaction (SIGUSR1, &sa, NULL);
     128      xsigaction (SIGUSR2, &sa, NULL);
     129      spawn_signal_test ("SIG_IGN", NULL);
     130    }
     131  
     132    {
     133      /* Check if SIG_IGN handlers are set to SIG_DFL.  */
     134      posix_spawnattr_t attr;
     135      posix_spawnattr_init (&attr);
     136      sigset_t mask;
     137      sigemptyset (&mask);
     138      sigaddset (&mask, SIGUSR1);
     139      sigaddset (&mask, SIGUSR2);
     140      posix_spawnattr_setsigdefault (&attr, &mask);
     141      posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF);
     142      spawn_signal_test ("SIG_DFL", &attr);
     143      posix_spawnattr_destroy (&attr);
     144    }
     145  }
     146  
     147  static int
     148  do_test (int argc, char *argv[])
     149  {
     150    /* We must have either:
     151  
     152       - one or four parameters if called initially:
     153         + argv[1]: path for ld.so        optional
     154         + argv[2]: "--library-path"      optional
     155         + argv[3]: the library path      optional
     156         + argv[4]: the application name
     157  
     158       - six parameters left if called through re-execution:
     159         + argv[1]: the application name
     160         + argv[2]: check SIG_IGN/SIG_DFL.
     161  
     162       * When built with --enable-hardcoded-path-in-tests or issued without
     163         using the loader directly.  */
     164  
     165    if (restart)
     166      handle_restart (argc - 1, &argv[1]);
     167  
     168    TEST_VERIFY_EXIT (argc == 2 || argc == 5);
     169  
     170    int i;
     171    for (i = 0; i < argc - 1; i++)
     172      spargs[i] = argv[i + 1];
     173    spargs[i++] = (char *) "--direct";
     174    spargs[i++] = (char *) "--restart";
     175    check_type_argc = i++;
     176    spargs[i] = NULL;
     177  
     178  
     179    do_test_signals ();
     180  
     181    return 0;
     182  }
     183  
     184  #define TEST_FUNCTION_ARGV do_test
     185  #include <support/test-driver.c>