(root)/
glibc-2.38/
support/
support_test_main.c
       1  /* Main worker function for the test driver.
       2     Copyright (C) 1998-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     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <support/test-driver.h>
      20  #include <support/check.h>
      21  #include <support/temp_file-internal.h>
      22  #include <support/support.h>
      23  
      24  #include <assert.h>
      25  #include <errno.h>
      26  #include <getopt.h>
      27  #include <malloc.h>
      28  #include <signal.h>
      29  #include <stdbool.h>
      30  #include <stdlib.h>
      31  #include <string.h>
      32  #include <sys/param.h>
      33  #include <sys/resource.h>
      34  #include <sys/time.h>
      35  #include <sys/types.h>
      36  #include <sys/wait.h>
      37  #include <time.h>
      38  #include <unistd.h>
      39  
      40  #include <xstdio.h>
      41  
      42  static const struct option default_options[] =
      43  {
      44    TEST_DEFAULT_OPTIONS
      45    { NULL, 0, NULL, 0 }
      46  };
      47  
      48  /* Show people how to run the program.  */
      49  static void
      50  usage (const struct option *options)
      51  {
      52    size_t i;
      53  
      54    printf ("Usage: %s [options]\n"
      55            "\n"
      56            "Environment Variables:\n"
      57            "  TIMEOUTFACTOR          An integer used to scale the timeout\n"
      58            "  TMPDIR                 Where to place temporary files\n"
      59            "  TEST_COREDUMPS         Do not disable coredumps if set\n"
      60            "\n",
      61            program_invocation_short_name);
      62    printf ("Options:\n");
      63    for (i = 0; options[i].name; ++i)
      64      {
      65        int indent;
      66  
      67        indent = printf ("  --%s", options[i].name);
      68        if (options[i].has_arg == required_argument)
      69          indent += printf (" <arg>");
      70        printf ("%*s", 25 - indent, "");
      71        switch (options[i].val)
      72          {
      73          case 'v':
      74            printf ("Increase the output verbosity");
      75            break;
      76          case OPT_DIRECT:
      77            printf ("Run the test directly (instead of forking & monitoring)");
      78            break;
      79          case OPT_TESTDIR:
      80            printf ("Override the TMPDIR env var");
      81            break;
      82          }
      83        printf ("\n");
      84      }
      85  }
      86  
      87  /* The PID of the test process.  */
      88  static pid_t test_pid;
      89  
      90  /* The cleanup handler passed to test_main.  */
      91  static void (*cleanup_function) (void);
      92  
      93  static void
      94  print_timestamp (const char *what, struct timespec tv)
      95  {
      96    struct tm tm;
      97    /* Casts of tv.tv_nsec below are necessary because the type of
      98       tv_nsec is not literally long int on all supported platforms.  */
      99    if (gmtime_r (&tv.tv_sec, &tm) == NULL)
     100      printf ("%s: %lld.%09ld\n",
     101              what, (long long int) tv.tv_sec, (long int) tv.tv_nsec);
     102    else
     103      printf ("%s: %04d-%02d-%02dT%02d:%02d:%02d.%09ld\n",
     104              what, 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
     105              tm.tm_hour, tm.tm_min, tm.tm_sec, (long int) tv.tv_nsec);
     106  }
     107  
     108  /* Timeout handler.  We kill the child and exit with an error.  */
     109  static void
     110  __attribute__ ((noreturn))
     111  signal_handler (int sig)
     112  {
     113    int killed;
     114    int status;
     115  
     116    /* Do this first to avoid further interference from the
     117       subprocess.  */
     118    struct timespec now;
     119    clock_gettime (CLOCK_REALTIME, &now);
     120    struct stat64 st;
     121    bool st_available = fstat64 (STDOUT_FILENO, &st) == 0 && st.st_mtime != 0;
     122  
     123    assert (test_pid > 1);
     124    /* Kill the whole process group.  */
     125    kill (-test_pid, SIGKILL);
     126    /* In case setpgid failed in the child, kill it individually too.  */
     127    kill (test_pid, SIGKILL);
     128  
     129    /* Wait for it to terminate.  */
     130    int i;
     131    for (i = 0; i < 5; ++i)
     132      {
     133        killed = waitpid (test_pid, &status, WNOHANG|WUNTRACED);
     134        if (killed != 0)
     135          break;
     136  
     137        /* Delay, give the system time to process the kill.  If the
     138           nanosleep() call return prematurely, all the better.  We
     139           won't restart it since this probably means the child process
     140           finally died.  */
     141        struct timespec ts;
     142        ts.tv_sec = 0;
     143        ts.tv_nsec = 100000000;
     144        nanosleep (&ts, NULL);
     145      }
     146    if (killed != 0 && killed != test_pid)
     147      {
     148        printf ("Failed to kill test process: %m\n");
     149        exit (1);
     150      }
     151  
     152    if (cleanup_function != NULL)
     153      cleanup_function ();
     154  
     155    if (sig == SIGINT)
     156      {
     157        signal (sig, SIG_DFL);
     158        raise (sig);
     159      }
     160  
     161    if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
     162      puts ("Timed out: killed the child process");
     163    else if (WIFSTOPPED (status))
     164      printf ("Timed out: the child process was %s\n",
     165              strsignal (WSTOPSIG (status)));
     166    else if (WIFSIGNALED (status))
     167      printf ("Timed out: the child process got signal %s\n",
     168              strsignal (WTERMSIG (status)));
     169    else
     170      printf ("Timed out: killed the child process but it exited %d\n",
     171              WEXITSTATUS (status));
     172  
     173    print_timestamp ("Termination time", now);
     174    if (st_available)
     175      print_timestamp ("Last write to standard output", st.st_mtim);
     176  
     177    /* Exit with an error.  */
     178    exit (1);
     179  }
     180  
     181  /* This must be volatile as it will be modified by the debugger.  */
     182  static volatile int wait_for_debugger = 0;
     183  
     184  /* Run test_function or test_function_argv.  */
     185  static int
     186  run_test_function (int argc, char **argv, const struct test_config *config)
     187  {
     188    const char *wfd = getenv("WAIT_FOR_DEBUGGER");
     189    if (wfd != NULL)
     190      wait_for_debugger = atoi (wfd);
     191    if (wait_for_debugger)
     192      {
     193        pid_t mypid;
     194        FILE *gdb_script;
     195        char *gdb_script_name;
     196        int inside_container = 0;
     197  
     198        mypid = getpid();
     199        if (mypid < 3)
     200  	{
     201  	  const char *outside_pid = getenv("PID_OUTSIDE_CONTAINER");
     202  	  if (outside_pid)
     203  	    {
     204  	      mypid = atoi (outside_pid);
     205  	      inside_container = 1;
     206  	    }
     207  	}
     208  
     209        gdb_script_name = (char *) xmalloc (strlen (argv[0]) + strlen (".gdb") + 1);
     210        sprintf (gdb_script_name, "%s.gdb", argv[0]);
     211        gdb_script = xfopen (gdb_script_name, "w");
     212  
     213        fprintf (stderr, "Waiting for debugger, test process is pid %d\n", mypid);
     214        fprintf (stderr, "gdb -x %s\n", gdb_script_name);
     215        if (inside_container)
     216  	fprintf (gdb_script, "set sysroot %s/testroot.root\n", support_objdir_root);
     217        fprintf (gdb_script, "file\n");
     218        fprintf (gdb_script, "file %s\n", argv[0]);
     219        fprintf (gdb_script, "symbol-file %s\n", argv[0]);
     220        fprintf (gdb_script, "exec-file %s\n", argv[0]);
     221        fprintf (gdb_script, "attach %ld\n", (long int) mypid);
     222        fprintf (gdb_script, "set wait_for_debugger = 0\n");
     223        fclose (gdb_script);
     224        free (gdb_script_name);
     225      }
     226  
     227    /* Wait for the debugger to set wait_for_debugger to zero.  */
     228    while (wait_for_debugger)
     229      usleep (1000);
     230  
     231    if (config->run_command_mode)
     232      {
     233        /* In run-command-mode, the child process executes the command line
     234  	 arguments as a new program.  */
     235        char **argv_ = xmalloc (sizeof (char *) * argc);
     236        memcpy (argv_, &argv[1], sizeof (char *) * (argc - 1));
     237        argv_[argc - 1] = NULL;
     238        execv (argv_[0], argv_);
     239        printf ("error: should not return here\n");
     240        exit (1);
     241      }
     242  
     243    if (config->test_function != NULL)
     244      return config->test_function ();
     245    else if (config->test_function_argv != NULL)
     246      return config->test_function_argv (argc, argv);
     247    else
     248      {
     249        printf ("error: no test function defined\n");
     250        exit (1);
     251      }
     252  }
     253  
     254  static bool test_main_called;
     255  
     256  const char *test_dir = NULL;
     257  unsigned int test_verbose = 0;
     258  
     259  /* If test failure reporting has been linked in, it may contribute
     260     additional test failures.  */
     261  static int
     262  adjust_exit_status (int status)
     263  {
     264    if (support_report_failure != NULL)
     265      return support_report_failure (status);
     266    return status;
     267  }
     268  
     269  int
     270  support_test_main (int argc, char **argv, const struct test_config *config)
     271  {
     272    if (test_main_called)
     273      {
     274        printf ("error: test_main called for a second time\n");
     275        exit (1);
     276      }
     277    test_main_called = true;
     278    const struct option *options;
     279    if (config->options != NULL)
     280      options = config->options;
     281    else
     282      options = default_options;
     283  
     284    cleanup_function = config->cleanup_function;
     285  
     286    int direct = 0;       /* Directly call the test function?  */
     287    int status;
     288    int opt;
     289    unsigned int timeoutfactor = TIMEOUTFACTOR;
     290    pid_t termpid;
     291  
     292    /* If we're debugging the test, we need to disable timeouts and use
     293       the initial pid (esp if we're running inside a container).  */
     294    if (getenv("WAIT_FOR_DEBUGGER") != NULL)
     295      direct = 1;
     296  
     297    if (!config->no_mallopt)
     298      {
     299        /* Make uses of freed and uninitialized memory known.  Do not
     300           pull in a definition for mallopt if it has not been defined
     301           already.  */
     302        extern __typeof__ (mallopt) mallopt __attribute__ ((weak));
     303        if (mallopt != NULL)
     304          mallopt (M_PERTURB, 42);
     305      }
     306  
     307    while ((opt = getopt_long (argc, argv, config->optstring, options, NULL))
     308  	 != -1)
     309      switch (opt)
     310        {
     311        case '?':
     312          usage (options);
     313          exit (1);
     314        case 'v':
     315          ++test_verbose;
     316          break;
     317        case OPT_DIRECT:
     318          direct = 1;
     319          break;
     320        case OPT_TESTDIR:
     321          test_dir = optarg;
     322          break;
     323        default:
     324          if (config->cmdline_function != NULL)
     325            config->cmdline_function (opt);
     326        }
     327  
     328    /* If set, read the test TIMEOUTFACTOR value from the environment.
     329       This value is used to scale the default test timeout values. */
     330    char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
     331    if (envstr_timeoutfactor != NULL)
     332      {
     333        char *envstr_conv = envstr_timeoutfactor;
     334        unsigned long int env_fact;
     335  
     336        env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
     337        if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
     338          timeoutfactor = MAX (env_fact, 1);
     339      }
     340  
     341    /* Set TMPDIR to specified test directory.  */
     342    if (test_dir != NULL)
     343      {
     344        setenv ("TMPDIR", test_dir, 1);
     345  
     346        if (chdir (test_dir) < 0)
     347          {
     348            printf ("chdir: %m\n");
     349            exit (1);
     350          }
     351      }
     352    else
     353      {
     354        test_dir = getenv ("TMPDIR");
     355        if (test_dir == NULL || test_dir[0] == '\0')
     356          test_dir = "/tmp";
     357      }
     358    if (support_set_test_dir != NULL)
     359      support_set_test_dir (test_dir);
     360  
     361    int timeout = config->timeout;
     362    if (timeout == 0)
     363      timeout =  DEFAULT_TIMEOUT;
     364  
     365    /* Make sure we see all message, even those on stdout.  */
     366    if (!config->no_setvbuf)
     367      setvbuf (stdout, NULL, _IONBF, 0);
     368  
     369    /* Make sure temporary files are deleted.  */
     370    if (support_delete_temp_files != NULL)
     371        atexit (support_delete_temp_files);
     372  
     373    /* Correct for the possible parameters.  */
     374    argv[optind - 1] = argv[0];
     375    argv += optind - 1;
     376    argc -= optind - 1;
     377  
     378    /* Call the initializing function, if one is available.  */
     379    if (config->prepare_function != NULL)
     380      config->prepare_function (argc, argv);
     381  
     382    const char *envstr_direct = getenv ("TEST_DIRECT");
     383    if (envstr_direct != NULL)
     384      {
     385        FILE *f = fopen (envstr_direct, "w");
     386        if (f == NULL)
     387          {
     388            printf ("cannot open TEST_DIRECT output file '%s': %m\n",
     389                    envstr_direct);
     390            exit (1);
     391          }
     392  
     393        fprintf (f, "timeout=%u\ntimeoutfactor=%u\n",
     394                 config->timeout, timeoutfactor);
     395        if (config->expected_status != 0)
     396          fprintf (f, "exit=%u\n", config->expected_status);
     397        if (config->expected_signal != 0)
     398          fprintf (f, "signal=%s\n", strsignal (config->expected_signal));
     399  
     400        if (support_print_temp_files != NULL)
     401          support_print_temp_files (f);
     402  
     403        fclose (f);
     404        direct = 1;
     405      }
     406  
     407    bool disable_coredumps;
     408    {
     409      const char *coredumps = getenv ("TEST_COREDUMPS");
     410      disable_coredumps = coredumps == NULL || coredumps[0] == '\0';
     411    }
     412  
     413    /* If we are not expected to fork run the function immediately.  */
     414    if (direct)
     415      return adjust_exit_status (run_test_function (argc, argv, config));
     416  
     417    /* Set up the test environment:
     418       - prevent core dumps
     419       - set up the timer
     420       - fork and execute the function.  */
     421  
     422    test_pid = fork ();
     423    if (test_pid == 0)
     424      {
     425        /* This is the child.  */
     426        if (disable_coredumps)
     427          {
     428            /* Try to avoid dumping core.  This is necessary because we
     429               run the test from the source tree, and the coredumps
     430               would end up there (and not in the build tree).  */
     431            struct rlimit core_limit;
     432            core_limit.rlim_cur = 0;
     433            core_limit.rlim_max = 0;
     434            setrlimit (RLIMIT_CORE, &core_limit);
     435          }
     436  
     437        /* We put the test process in its own pgrp so that if it bogusly
     438           generates any job control signals, they won't hit the whole build.  */
     439        if (setpgid (0, 0) != 0)
     440          printf ("Failed to set the process group ID: %m\n");
     441  
     442        /* Execute the test function and exit with the return value.   */
     443        exit (run_test_function (argc, argv, config));
     444      }
     445    else if (test_pid < 0)
     446      {
     447        printf ("Cannot fork test program: %m\n");
     448        exit (1);
     449      }
     450  
     451    /* Set timeout.  */
     452    signal (SIGALRM, signal_handler);
     453    alarm (timeout * timeoutfactor);
     454  
     455    /* Make sure we clean up if the wrapper gets interrupted.  */
     456    signal (SIGINT, signal_handler);
     457  
     458    /* Wait for the regular termination.  */
     459    termpid = TEMP_FAILURE_RETRY (waitpid (test_pid, &status, 0));
     460    if (termpid == -1)
     461      {
     462        printf ("Waiting for test program failed: %m\n");
     463        exit (1);
     464      }
     465    if (termpid != test_pid)
     466      {
     467        printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
     468                (long int) test_pid, (long int) termpid);
     469        exit (1);
     470      }
     471  
     472    /* Process terminated normally without timeout etc.  */
     473    if (WIFEXITED (status))
     474      {
     475        if (config->expected_status == 0)
     476          {
     477            if (config->expected_signal == 0)
     478              /* Exit with the return value of the test.  */
     479              return adjust_exit_status (WEXITSTATUS (status));
     480            else
     481              {
     482                printf ("Expected signal '%s' from child, got none\n",
     483                        strsignal (config->expected_signal));
     484                exit (1);
     485              }
     486          }
     487        else
     488          {
     489            /* Non-zero exit status is expected */
     490            if (WEXITSTATUS (status) != config->expected_status)
     491              {
     492                printf ("Expected status %d, got %d\n",
     493                        config->expected_status, WEXITSTATUS (status));
     494                exit (1);
     495              }
     496          }
     497        return adjust_exit_status (0);
     498      }
     499    /* Process was killed by timer or other signal.  */
     500    else
     501      {
     502        if (config->expected_signal == 0)
     503          {
     504            printf ("Didn't expect signal from child: got `%s'\n",
     505                    strsignal (WTERMSIG (status)));
     506            exit (1);
     507          }
     508        else if (WTERMSIG (status) != config->expected_signal)
     509          {
     510            printf ("Incorrect signal from child: got `%s', need `%s'\n",
     511                    strsignal (WTERMSIG (status)),
     512                    strsignal (config->expected_signal));
     513            exit (1);
     514          }
     515  
     516        return adjust_exit_status (0);
     517      }
     518  }