test-skeleton.c: Do not set RLIMIT_DATA [BZ #19648]
[platform/upstream/glibc.git] / test-skeleton.c
1 /* Skeleton for test programs.
2    Copyright (C) 1998-2016 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <assert.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <getopt.h>
24 #include <malloc.h>
25 #include <paths.h>
26 #include <search.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/resource.h>
33 #include <sys/wait.h>
34 #include <sys/param.h>
35 #include <time.h>
36
37 /* The test function is normally called `do_test' and it is called
38    with argc and argv as the arguments.  We nevertheless provide the
39    possibility to overwrite this name.  */
40 #ifndef TEST_FUNCTION
41 # define TEST_FUNCTION do_test (argc, argv)
42 #endif
43
44 #ifndef TEST_DATA_LIMIT
45 # define TEST_DATA_LIMIT (64 << 20) /* Data limit (bytes) to run with.  */
46 #endif
47
48 #ifndef TIMEOUT
49   /* Default timeout is twenty seconds.  Tests should normally complete faster
50      than this, but if they don't, that's abnormal (a bug) anyways.  */
51 # define TIMEOUT 20
52 #endif
53
54 #define OPT_DIRECT 1000
55 #define OPT_TESTDIR 1001
56
57 static struct option options[] =
58 {
59 #ifdef CMDLINE_OPTIONS
60   CMDLINE_OPTIONS
61 #endif
62   { "direct", no_argument, NULL, OPT_DIRECT },
63   { "test-dir", required_argument, NULL, OPT_TESTDIR },
64   { NULL, 0, NULL, 0 }
65 };
66
67 /* PID of the test itself.  */
68 static pid_t pid;
69
70 /* Directory to place temporary files in.  */
71 static const char *test_dir;
72
73 /* List of temporary files.  */
74 struct temp_name_list
75 {
76   struct qelem q;
77   char *name;
78 } *temp_name_list;
79
80 /* Add temporary files in list.  */
81 static void
82 __attribute__ ((unused))
83 add_temp_file (const char *name)
84 {
85   struct temp_name_list *newp
86     = (struct temp_name_list *) calloc (sizeof (*newp), 1);
87   char *newname = strdup (name);
88   if (newp != NULL && newname != NULL)
89     {
90       newp->name = newname;
91       if (temp_name_list == NULL)
92         temp_name_list = (struct temp_name_list *) &newp->q;
93       else
94         insque (newp, temp_name_list);
95     }
96   else
97     free (newp);
98 }
99
100 /* Delete all temporary files.  */
101 static void
102 delete_temp_files (void)
103 {
104   while (temp_name_list != NULL)
105     {
106       remove (temp_name_list->name);
107       free (temp_name_list->name);
108
109       struct temp_name_list *next
110         = (struct temp_name_list *) temp_name_list->q.q_forw;
111       free (temp_name_list);
112       temp_name_list = next;
113     }
114 }
115
116 /* Create a temporary file.  Return the opened file descriptor on
117    success, or -1 on failure.  Write the file name to *FILENAME if
118    FILENAME is not NULL.  In this case, the caller is expected to free
119    *FILENAME.  */
120 static int
121 __attribute__ ((unused))
122 create_temp_file (const char *base, char **filename)
123 {
124   char *fname;
125   int fd;
126
127   fname = (char *) malloc (strlen (test_dir) + 1 + strlen (base)
128                            + sizeof ("XXXXXX"));
129   if (fname == NULL)
130     {
131       puts ("out of memory");
132       return -1;
133     }
134   strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
135
136   fd = mkstemp (fname);
137   if (fd == -1)
138     {
139       printf ("cannot open temporary file '%s': %m\n", fname);
140       free (fname);
141       return -1;
142     }
143
144   add_temp_file (fname);
145   if (filename != NULL)
146     *filename = fname;
147   else
148     free (fname);
149
150   return fd;
151 }
152
153 /* Timeout handler.  We kill the child and exit with an error.  */
154 static void
155 __attribute__ ((noreturn))
156 signal_handler (int sig __attribute__ ((unused)))
157 {
158   int killed;
159   int status;
160
161   assert (pid > 1);
162   /* Kill the whole process group.  */
163   kill (-pid, SIGKILL);
164   /* In case setpgid failed in the child, kill it individually too.  */
165   kill (pid, SIGKILL);
166
167   /* Wait for it to terminate.  */
168   int i;
169   for (i = 0; i < 5; ++i)
170     {
171       killed = waitpid (pid, &status, WNOHANG|WUNTRACED);
172       if (killed != 0)
173         break;
174
175       /* Delay, give the system time to process the kill.  If the
176          nanosleep() call return prematurely, all the better.  We
177          won't restart it since this probably means the child process
178          finally died.  */
179       struct timespec ts;
180       ts.tv_sec = 0;
181       ts.tv_nsec = 100000000;
182       nanosleep (&ts, NULL);
183     }
184   if (killed != 0 && killed != pid)
185     {
186       printf ("Failed to kill test process: %m\n");
187       exit (1);
188     }
189
190 #ifdef CLEANUP_HANDLER
191   CLEANUP_HANDLER;
192 #endif
193
194   if (sig == SIGINT)
195     {
196       signal (sig, SIG_DFL);
197       raise (sig);
198     }
199
200   /* If we expected this signal: good!  */
201 #ifdef EXPECTED_SIGNAL
202   if (EXPECTED_SIGNAL == SIGALRM)
203     exit (0);
204 #endif
205
206   if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
207     puts ("Timed out: killed the child process");
208   else if (WIFSTOPPED (status))
209     printf ("Timed out: the child process was %s\n",
210             strsignal (WSTOPSIG (status)));
211   else if (WIFSIGNALED (status))
212     printf ("Timed out: the child process got signal %s\n",
213             strsignal (WTERMSIG (status)));
214   else
215     printf ("Timed out: killed the child process but it exited %d\n",
216             WEXITSTATUS (status));
217
218   /* Exit with an error.  */
219   exit (1);
220 }
221
222 /* Avoid all the buffer overflow messages on stderr.  */
223 static void
224 __attribute__ ((unused))
225 ignore_stderr (void)
226 {
227   int fd = open (_PATH_DEVNULL, O_WRONLY);
228   if (fd == -1)
229     close (STDERR_FILENO);
230   else
231     {
232       dup2 (fd, STDERR_FILENO);
233       close (fd);
234     }
235   setenv ("LIBC_FATAL_STDERR_", "1", 1);
236 }
237
238 /* Set fortification error handler.  Used when tests want to verify that bad
239    code is caught by the library.  */
240 static void
241 __attribute__ ((unused))
242 set_fortify_handler (void (*handler) (int sig))
243 {
244   struct sigaction sa;
245
246   sa.sa_handler = handler;
247   sa.sa_flags = 0;
248   sigemptyset (&sa.sa_mask);
249
250   sigaction (SIGABRT, &sa, NULL);
251   ignore_stderr ();
252 }
253
254 /* Show people how to run the program.  */
255 static void
256 usage (void)
257 {
258   size_t i;
259
260   printf ("Usage: %s [options]\n"
261           "\n"
262           "Environment Variables:\n"
263           "  TIMEOUTFACTOR          An integer used to scale the timeout\n"
264           "  TMPDIR                 Where to place temporary files\n"
265           "\n",
266           program_invocation_short_name);
267   printf ("Options:\n");
268   for (i = 0; options[i].name; ++i)
269     {
270       int indent;
271
272       indent = printf ("  --%s", options[i].name);
273       if (options[i].has_arg == required_argument)
274         indent += printf (" <arg>");
275       printf ("%*s", 25 - indent, "");
276       switch (options[i].val)
277         {
278         case OPT_DIRECT:
279           printf ("Run the test directly (instead of forking & monitoring)");
280           break;
281         case OPT_TESTDIR:
282           printf ("Override the TMPDIR env var");
283           break;
284         }
285       printf ("\n");
286     }
287 }
288
289 /* We provide the entry point here.  */
290 int
291 main (int argc, char *argv[])
292 {
293   int direct = 0;       /* Directly call the test function?  */
294   int status;
295   int opt;
296   unsigned int timeoutfactor = 1;
297   pid_t termpid;
298
299   /* Make uses of freed and uninitialized memory known.  */
300   mallopt (M_PERTURB, 42);
301
302 #ifdef STDOUT_UNBUFFERED
303   setbuf (stdout, NULL);
304 #endif
305
306   while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
307     switch (opt)
308       {
309       case '?':
310         usage ();
311         exit (1);
312       case OPT_DIRECT:
313         direct = 1;
314         break;
315       case OPT_TESTDIR:
316         test_dir = optarg;
317         break;
318 #ifdef CMDLINE_PROCESS
319         CMDLINE_PROCESS
320 #endif
321       }
322
323   /* If set, read the test TIMEOUTFACTOR value from the environment.
324      This value is used to scale the default test timeout values. */
325   char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
326   if (envstr_timeoutfactor != NULL)
327     {
328       char *envstr_conv = envstr_timeoutfactor;
329       unsigned long int env_fact;
330
331       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
332       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
333         timeoutfactor = MAX (env_fact, 1);
334     }
335
336   /* Set TMPDIR to specified test directory.  */
337   if (test_dir != NULL)
338     {
339       setenv ("TMPDIR", test_dir, 1);
340
341       if (chdir (test_dir) < 0)
342         {
343           printf ("chdir: %m\n");
344           exit (1);
345         }
346     }
347   else
348     {
349       test_dir = getenv ("TMPDIR");
350       if (test_dir == NULL || test_dir[0] == '\0')
351         test_dir = "/tmp";
352     }
353
354   /* Make sure we see all message, even those on stdout.  */
355   setvbuf (stdout, NULL, _IONBF, 0);
356
357   /* Make sure temporary files are deleted.  */
358   atexit (delete_temp_files);
359
360   /* Correct for the possible parameters.  */
361   argv[optind - 1] = argv[0];
362   argv += optind - 1;
363   argc -= optind - 1;
364
365   /* Call the initializing function, if one is available.  */
366 #ifdef PREPARE
367   PREPARE (argc, argv);
368 #endif
369
370   const char *envstr_direct = getenv ("TEST_DIRECT");
371   if (envstr_direct != NULL)
372     {
373       FILE *f = fopen (envstr_direct, "w");
374       if (f == NULL)
375         {
376           printf ("cannot open TEST_DIRECT output file '%s': %m\n",
377                   envstr_direct);
378           exit (1);
379         }
380
381       fprintf (f, "timeout=%u\ntimeoutfactor=%u\n", TIMEOUT, timeoutfactor);
382 #ifdef EXPECTED_STATUS
383       fprintf (f, "exit=%u\n", EXPECTED_STATUS);
384 #endif
385 #ifdef EXPECTED_SIGNAL
386       switch (EXPECTED_SIGNAL)
387         {
388         default: abort ();
389 # define init_sig(signo, name, text) \
390         case signo: fprintf (f, "signal=%s\n", name); break;
391 # include <siglist.h>
392 # undef init_sig
393         }
394 #endif
395
396       if (temp_name_list != NULL)
397         {
398           struct temp_name_list *n;
399           fprintf (f, "temp_files=(\n");
400           for (n = temp_name_list;
401                n != NULL;
402                n = (struct temp_name_list *) n->q.q_forw)
403             fprintf (f, "  '%s'\n", n->name);
404           fprintf (f, ")\n");
405         }
406
407       fclose (f);
408       direct = 1;
409     }
410
411   /* If we are not expected to fork run the function immediately.  */
412   if (direct)
413     return TEST_FUNCTION;
414
415   /* Set up the test environment:
416      - prevent core dumps
417      - set up the timer
418      - fork and execute the function.  */
419
420   pid = fork ();
421   if (pid == 0)
422     {
423       /* This is the child.  */
424 #ifdef RLIMIT_CORE
425       /* Try to avoid dumping core.  */
426       struct rlimit core_limit;
427       core_limit.rlim_cur = 0;
428       core_limit.rlim_max = 0;
429       setrlimit (RLIMIT_CORE, &core_limit);
430 #endif
431
432       /* We put the test process in its own pgrp so that if it bogusly
433          generates any job control signals, they won't hit the whole build.  */
434       if (setpgid (0, 0) != 0)
435         printf ("Failed to set the process group ID: %m\n");
436
437       /* Execute the test function and exit with the return value.   */
438       exit (TEST_FUNCTION);
439     }
440   else if (pid < 0)
441     {
442       printf ("Cannot fork test program: %m\n");
443       exit (1);
444     }
445
446   /* Set timeout.  */
447   signal (SIGALRM, signal_handler);
448   alarm (TIMEOUT * timeoutfactor);
449
450   /* Make sure we clean up if the wrapper gets interrupted.  */
451   signal (SIGINT, signal_handler);
452
453   /* Wait for the regular termination.  */
454   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
455   if (termpid == -1)
456     {
457       printf ("Waiting for test program failed: %m\n");
458       exit (1);
459     }
460   if (termpid != pid)
461     {
462       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
463               (long int) pid, (long int) termpid);
464       exit (1);
465     }
466
467   /* Process terminated normaly without timeout etc.  */
468   if (WIFEXITED (status))
469     {
470 #ifndef EXPECTED_STATUS
471 # ifndef EXPECTED_SIGNAL
472       /* Simply exit with the return value of the test.  */
473       return WEXITSTATUS (status);
474 # else
475       printf ("Expected signal '%s' from child, got none\n",
476               strsignal (EXPECTED_SIGNAL));
477       exit (1);
478 # endif
479 #else
480       if (WEXITSTATUS (status) != EXPECTED_STATUS)
481         {
482           printf ("Expected status %d, got %d\n",
483                   EXPECTED_STATUS, WEXITSTATUS (status));
484           exit (1);
485         }
486
487       return 0;
488 #endif
489     }
490   /* Process was killed by timer or other signal.  */
491   else
492     {
493 #ifndef EXPECTED_SIGNAL
494       printf ("Didn't expect signal from child: got `%s'\n",
495               strsignal (WTERMSIG (status)));
496       exit (1);
497 #else
498       if (WTERMSIG (status) != EXPECTED_SIGNAL)
499         {
500           printf ("Incorrect signal from child: got `%s', need `%s'\n",
501                   strsignal (WTERMSIG (status)),
502                   strsignal (EXPECTED_SIGNAL));
503           exit (1);
504         }
505
506       return 0;
507 #endif
508     }
509 }