1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-09-11 12:10:50 +03:00

support: Introduce new subdirectory for test infrastructure

The new test driver in <support/test-driver.c> has feature parity with
the old one.  The main difference is that its hooking mechanism is
based on functions and function pointers instead of macros.  This
commit also implements a new environment variable, TEST_COREDUMPS,
which disables the code which disables coredumps (that is, it enables
them if the invocation environment has not disabled them).

<test-skeleton.c> defines wrapper functions so that it is possible to
use existing macros with the new-style hook functionality.

This commit changes only a few test cases to the new test driver, to
make sure that it works as expected.
This commit is contained in:
Florian Weimer
2016-12-09 08:18:27 +01:00
parent c03073774f
commit c23de0aacb
59 changed files with 2204 additions and 968 deletions

64
support/Makefile Normal file
View File

@@ -0,0 +1,64 @@
# Makefile for support library, used only at build and test time
# Copyright (C) 2016 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# The GNU C Library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with the GNU C Library; if not, see
# <http://www.gnu.org/licenses/>.
subdir := support
include ../Makeconfig
extra-libs := libsupport
extra-libs-others = $(extra-libs)
extra-libs-noinstall := $(extra-libs)
libsupport-routines = \
check \
delayed_exit \
ignore_stderr \
oom_error \
set_fortify_handler \
support_test_main \
temp_file \
write_message \
xasprintf \
xcalloc \
xmalloc \
xpthread_barrier_destroy \
xpthread_barrier_init \
xpthread_barrier_wait \
xpthread_cancel \
xpthread_check_return \
xpthread_cond_wait \
xpthread_create \
xpthread_detach \
xpthread_join \
xpthread_mutex_lock \
xpthread_mutex_unlock \
xpthread_sigmask \
xpthread_spin_lock \
xpthread_spin_unlock \
xrealloc \
libsupport-static-only-routines := $(libsupport-routines)
# Only build one variant of the library.
libsupport-inhibit-o := .os
ifeq ($(build-shared),yes)
libsupport-inhibit-o += .o
endif
tests = README-testing
include ../Rules

29
support/README Normal file
View File

@@ -0,0 +1,29 @@
This subdirectory contains infrastructure which is not put into
installed libraries, but may be linked into programs (installed or
not) and tests.
# Error-checking wrappers
These wrappers test for error return codes an terminate the process on
error. They are declared in these header files:
* support.h
* xsignal.h
* xthread.h
In general, new wrappers should be added to support.h if possible.
However, support.h must remain fully compatible with C90 and therefore
cannot include headers which use identifers not reserved in C90. If
the wrappers need additional types, additional headers such as
signal.h need to be introduced.
# Test framework
The test framework provides a main program for tests, including a
timeout for hanging tests. See README-testing.c for a minimal
example, and test-driver.c for details how to use it. The following
header files provide related declarations:
* check.h
* temp_file.h
* test-driver.h

19
support/README-testing.c Normal file
View File

@@ -0,0 +1,19 @@
/* This file contains an example test case which shows minimal use of
the test framework. Additional testing hooks are described in
<support/test-driver.c>. */
/* This function will be called from the test driver. */
static int
do_test (void)
{
if (3 == 5)
/* Indicate failure. */
return 1;
else
/* Indicate success. */
return 0;
}
/* This file references do_test above and contains the definition of
the main function. */
#include <support/test-driver.c>

53
support/check.c Normal file
View File

@@ -0,0 +1,53 @@
/* Support code for reporting test results.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/check.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
static void
print_failure (const char *file, int line, const char *format, va_list ap)
{
printf ("error: %s:%d: ", file, line);
vprintf (format, ap);
puts ("");
}
int
support_print_failure_impl (const char *file, int line,
const char *format, ...)
{
va_list ap;
va_start (ap, format);
print_failure (file, line, format, ap);
va_end (ap);
return 1;
}
void
support_exit_failure_impl (int status, const char *file, int line,
const char *format, ...)
{
va_list ap;
va_start (ap, format);
print_failure (file, line, format, ap);
va_end (ap);
exit (status);
}

49
support/check.h Normal file
View File

@@ -0,0 +1,49 @@
/* Macros for reporting test results.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef SUPPORT_CHECK_H
#define SUPPORT_CHECK_H
#include <sys/cdefs.h>
__BEGIN_DECLS
/* Print failure message to standard output and return 1. */
#define FAIL_RET(...) \
return support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__)
/* Print failure message and terminate the process with STATUS. */
#define FAIL_EXIT(status, ...) \
support_exit_failure_impl (status, __FILE__, __LINE__, __VA_ARGS__)
/* Print failure message and terminate with exit status 1. */
#define FAIL_EXIT1(...) \
support_exit_failure_impl (1, __FILE__, __LINE__, __VA_ARGS__)
int support_print_failure_impl (const char *file, int line,
const char *format, ...)
__attribute__ ((nonnull (1), format (printf, 3, 4)));
void support_exit_failure_impl (int exit_status,
const char *file, int line,
const char *format, ...)
__attribute__ ((noreturn, nonnull (2), format (printf, 4, 5)));
__END_DECLS
#endif /* SUPPORT_CHECK_H */

57
support/delayed_exit.c Normal file
View File

@@ -0,0 +1,57 @@
/* Time-triggered process termination.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
#include <support/xsignal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static void *
delayed_exit_thread (void *seconds_as_ptr)
{
int seconds = (uintptr_t) seconds_as_ptr;
struct timespec delay = { seconds, 0 };
struct timespec remaining = { 0 };
if (nanosleep (&delay, &remaining) != 0)
{
printf ("error: nanosleep: %m\n");
exit (1);
}
/* Exit the process sucessfully. */
exit (0);
return NULL;
}
void
delayed_exit (int seconds)
{
/* Create the new thread with all signals blocked. */
sigset_t all_blocked;
sigfillset (&all_blocked);
sigset_t old_set;
xpthread_sigmask (SIG_SETMASK, &all_blocked, &old_set);
/* Create a detached thread. */
pthread_t thr = xpthread_create
(NULL, delayed_exit_thread, (void *) (uintptr_t) seconds);
xpthread_detach (thr);
/* Restore the original signal mask. */
xpthread_sigmask (SIG_SETMASK, &old_set, NULL);
}

38
support/ignore_stderr.c Normal file
View File

@@ -0,0 +1,38 @@
/* Avoid all the buffer overflow messages on stderr.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <fcntl.h>
#include <paths.h>
#include <stdlib.h>
#include <unistd.h>
void
ignore_stderr (void)
{
int fd = open (_PATH_DEVNULL, O_WRONLY);
if (fd == -1)
close (STDERR_FILENO);
else
{
dup2 (fd, STDERR_FILENO);
close (fd);
}
setenv ("LIBC_FATAL_STDERR_", "1", 1);
}

29
support/oom_error.c Normal file
View File

@@ -0,0 +1,29 @@
/* Reporting out-of-memory errors.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <stdio.h>
#include <stdlib.h>
void
oom_error (const char *function, size_t size)
{
printf ("%s: unable to allocate %zu bytes: %m\n", function, size);
exit (1);
}

View File

@@ -0,0 +1,34 @@
/* Set signal handler for use in fortify tests.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <signal.h>
void
set_fortify_handler (void (*handler) (int sig))
{
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset (&sa.sa_mask);
sigaction (SIGABRT, &sa, NULL);
ignore_stderr ();
}

58
support/support.h Normal file
View File

@@ -0,0 +1,58 @@
/* Common extra functions.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This header file should only contain definitions compatible with
C90. (Using __attribute__ is fine because <features.h> provides a
fallback.) */
#ifndef SUPPORT_H
#define SUPPORT_H
#include <stddef.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
/* Write a message to standard output. Can be used in signal
handlers. */
void write_message (const char *message) __attribute__ ((nonnull (1)));
/* Avoid all the buffer overflow messages on stderr. */
void ignore_stderr (void);
/* Set fortification error handler. Used when tests want to verify that bad
code is caught by the library. */
void set_fortify_handler (void (*handler) (int sig));
/* Report an out-of-memory error for the allocation of SIZE bytes in
FUNCTION, terminating the process. */
void oom_error (const char *function, size_t size)
__attribute__ ((nonnull (1)));
/* Error-checking wrapper functions which terminate the process on
error. */
void *xmalloc (size_t) __attribute__ ((malloc));
void *xcalloc (size_t n, size_t s) __attribute__ ((malloc));
void *xrealloc (void *p, size_t n);
char *xasprintf (const char *format, ...)
__attribute__ ((format (printf, 1, 2), malloc));
__END_DECLS
#endif /* SUPPORT_H */

406
support/support_test_main.c Normal file
View File

@@ -0,0 +1,406 @@
/* Main worker function for the test driver.
Copyright (C) 1998-2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/test-driver.h>
#include <support/temp_file-internal.h>
#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <malloc.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
static const struct option default_options[] =
{
{ "direct", no_argument, NULL, OPT_DIRECT },
{ "test-dir", required_argument, NULL, OPT_TESTDIR },
{ NULL, 0, NULL, 0 }
};
/* Show people how to run the program. */
static void
usage (const struct option *options)
{
size_t i;
printf ("Usage: %s [options]\n"
"\n"
"Environment Variables:\n"
" TIMEOUTFACTOR An integer used to scale the timeout\n"
" TMPDIR Where to place temporary files\n"
" TEST_COREDUMPS Do not disable coredumps if set\n"
"\n",
program_invocation_short_name);
printf ("Options:\n");
for (i = 0; options[i].name; ++i)
{
int indent;
indent = printf (" --%s", options[i].name);
if (options[i].has_arg == required_argument)
indent += printf (" <arg>");
printf ("%*s", 25 - indent, "");
switch (options[i].val)
{
case OPT_DIRECT:
printf ("Run the test directly (instead of forking & monitoring)");
break;
case OPT_TESTDIR:
printf ("Override the TMPDIR env var");
break;
}
printf ("\n");
}
}
/* The PID of the test process. */
static pid_t test_pid;
/* The cleanup handler passed to test_main. */
static void (*cleanup_function) (void);
/* Timeout handler. We kill the child and exit with an error. */
static void
__attribute__ ((noreturn))
signal_handler (int sig)
{
int killed;
int status;
assert (test_pid > 1);
/* Kill the whole process group. */
kill (-test_pid, SIGKILL);
/* In case setpgid failed in the child, kill it individually too. */
kill (test_pid, SIGKILL);
/* Wait for it to terminate. */
int i;
for (i = 0; i < 5; ++i)
{
killed = waitpid (test_pid, &status, WNOHANG|WUNTRACED);
if (killed != 0)
break;
/* Delay, give the system time to process the kill. If the
nanosleep() call return prematurely, all the better. We
won't restart it since this probably means the child process
finally died. */
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 100000000;
nanosleep (&ts, NULL);
}
if (killed != 0 && killed != test_pid)
{
printf ("Failed to kill test process: %m\n");
exit (1);
}
if (cleanup_function != NULL)
cleanup_function ();
if (sig == SIGINT)
{
signal (sig, SIG_DFL);
raise (sig);
}
if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
puts ("Timed out: killed the child process");
else if (WIFSTOPPED (status))
printf ("Timed out: the child process was %s\n",
strsignal (WSTOPSIG (status)));
else if (WIFSIGNALED (status))
printf ("Timed out: the child process got signal %s\n",
strsignal (WTERMSIG (status)));
else
printf ("Timed out: killed the child process but it exited %d\n",
WEXITSTATUS (status));
/* Exit with an error. */
exit (1);
}
/* Run test_function or test_function_argv. */
static int
run_test_function (int argc, char **argv, const struct test_config *config)
{
if (config->test_function != NULL)
return config->test_function ();
else if (config->test_function_argv != NULL)
return config->test_function_argv (argc, argv);
else
{
printf ("error: no test function defined\n");
exit (1);
}
}
static bool test_main_called;
const char *test_dir = NULL;
int
support_test_main (int argc, char **argv, const struct test_config *config)
{
if (test_main_called)
{
printf ("error: test_main called for a second time\n");
exit (1);
}
test_main_called = true;
const struct option *options;
if (config->options != NULL)
options = config->options;
else
options = default_options;
cleanup_function = config->cleanup_function;
int direct = 0; /* Directly call the test function? */
int status;
int opt;
unsigned int timeoutfactor = 1;
pid_t termpid;
if (!config->no_mallopt)
{
/* Make uses of freed and uninitialized memory known. Do not
pull in a definition for mallopt if it has not been defined
already. */
extern __typeof__ (mallopt) mallopt __attribute__ ((weak));
if (mallopt != NULL)
mallopt (M_PERTURB, 42);
}
while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
switch (opt)
{
case '?':
usage (options);
exit (1);
case OPT_DIRECT:
direct = 1;
break;
case OPT_TESTDIR:
test_dir = optarg;
break;
default:
if (config->cmdline_function != NULL)
config->cmdline_function (opt);
}
/* If set, read the test TIMEOUTFACTOR value from the environment.
This value is used to scale the default test timeout values. */
char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
if (envstr_timeoutfactor != NULL)
{
char *envstr_conv = envstr_timeoutfactor;
unsigned long int env_fact;
env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
timeoutfactor = MAX (env_fact, 1);
}
/* Set TMPDIR to specified test directory. */
if (test_dir != NULL)
{
setenv ("TMPDIR", test_dir, 1);
if (chdir (test_dir) < 0)
{
printf ("chdir: %m\n");
exit (1);
}
}
else
{
test_dir = getenv ("TMPDIR");
if (test_dir == NULL || test_dir[0] == '\0')
test_dir = "/tmp";
}
if (support_set_test_dir != NULL)
support_set_test_dir (test_dir);
int timeout = config->timeout;
if (timeout == 0)
timeout = DEFAULT_TIMEOUT;
/* Make sure we see all message, even those on stdout. */
setvbuf (stdout, NULL, _IONBF, 0);
/* Make sure temporary files are deleted. */
if (support_delete_temp_files != NULL)
atexit (support_delete_temp_files);
/* Correct for the possible parameters. */
argv[optind - 1] = argv[0];
argv += optind - 1;
argc -= optind - 1;
/* Call the initializing function, if one is available. */
if (config->prepare_function != NULL)
config->prepare_function (argc, argv);
const char *envstr_direct = getenv ("TEST_DIRECT");
if (envstr_direct != NULL)
{
FILE *f = fopen (envstr_direct, "w");
if (f == NULL)
{
printf ("cannot open TEST_DIRECT output file '%s': %m\n",
envstr_direct);
exit (1);
}
fprintf (f, "timeout=%u\ntimeoutfactor=%u\n",
config->timeout, timeoutfactor);
if (config->expected_status != 0)
fprintf (f, "exit=%u\n", config->expected_status);
if (config->expected_signal != 0)
fprintf (f, "signal=%s\n", strsignal (config->expected_signal));
if (support_print_temp_files != NULL)
support_print_temp_files (f);
fclose (f);
direct = 1;
}
bool disable_coredumps;
{
const char *coredumps = getenv ("TEST_COREDUMPS");
disable_coredumps = coredumps == NULL || coredumps[0] == '\0';
}
/* If we are not expected to fork run the function immediately. */
if (direct)
return run_test_function (argc, argv, config);
/* Set up the test environment:
- prevent core dumps
- set up the timer
- fork and execute the function. */
pid_t test_pid = fork ();
if (test_pid == 0)
{
/* This is the child. */
if (disable_coredumps)
{
/* Try to avoid dumping core. This is necessary because we
run the test from the source tree, and the coredumps
would end up there (and not in the build tree). */
struct rlimit core_limit;
core_limit.rlim_cur = 0;
core_limit.rlim_max = 0;
setrlimit (RLIMIT_CORE, &core_limit);
}
/* We put the test process in its own pgrp so that if it bogusly
generates any job control signals, they won't hit the whole build. */
if (setpgid (0, 0) != 0)
printf ("Failed to set the process group ID: %m\n");
/* Execute the test function and exit with the return value. */
exit (run_test_function (argc, argv, config));
}
else if (test_pid < 0)
{
printf ("Cannot fork test program: %m\n");
exit (1);
}
/* Set timeout. */
signal (SIGALRM, signal_handler);
alarm (config->timeout * timeoutfactor);
/* Make sure we clean up if the wrapper gets interrupted. */
signal (SIGINT, signal_handler);
/* Wait for the regular termination. */
termpid = TEMP_FAILURE_RETRY (waitpid (test_pid, &status, 0));
if (termpid == -1)
{
printf ("Waiting for test program failed: %m\n");
exit (1);
}
if (termpid != test_pid)
{
printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
(long int) test_pid, (long int) termpid);
exit (1);
}
/* Process terminated normaly without timeout etc. */
if (WIFEXITED (status))
{
if (config->expected_status == 0)
{
if (config->expected_signal == 0)
/* Simply exit with the return value of the test. */
return WEXITSTATUS (status);
else
{
printf ("Expected signal '%s' from child, got none\n",
strsignal (config->expected_signal));
exit (1);
}
}
else
{
/* Non-zero exit status is expected */
if (WEXITSTATUS (status) != config->expected_status)
{
printf ("Expected status %d, got %d\n",
config->expected_status, WEXITSTATUS (status));
exit (1);
}
}
return 0;
}
/* Process was killed by timer or other signal. */
else
{
if (config->expected_signal == 0)
{
printf ("Didn't expect signal from child: got `%s'\n",
strsignal (WTERMSIG (status)));
exit (1);
}
else if (WTERMSIG (status) != config->expected_signal)
{
printf ("Incorrect signal from child: got `%s', need `%s'\n",
strsignal (WTERMSIG (status)),
strsignal (config->expected_signal));
exit (1);
}
return 0;
}
}

View File

@@ -0,0 +1,31 @@
/* Internal weak declarations for temporary file handling.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef SUPPORT_TEMP_FILE_INTERNAL_H
#define SUPPORT_TEMP_FILE_INTERNAL_H
/* These functions are called by the test driver if they are
defined. Tests should not call them directly. */
#include <stdio.h>
void support_set_test_dir (const char *name) __attribute__ ((weak));
void support_delete_temp_files (void) __attribute__ ((weak));
void support_print_temp_files (FILE *) __attribute__ ((weak));
#endif /* SUPPORT_TEMP_FILE_INTERNAL_H */

125
support/temp_file.c Normal file
View File

@@ -0,0 +1,125 @@
/* Temporary file handling for tests.
Copyright (C) 1998-2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This is required to get an mkstemp which can create large files on
some 32-bit platforms. */
#define _FILE_OFFSET_BITS 64
#include <support/temp_file.h>
#include <support/temp_file-internal.h>
#include <support/support.h>
#include <paths.h>
#include <search.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* List of temporary files. */
static struct temp_name_list
{
struct qelem q;
char *name;
} *temp_name_list;
/* Location of the temporary files. Set by the test skeleton via
support_set_test_dir. The string is not be freed. */
static const char *test_dir = _PATH_TMP;
void
add_temp_file (const char *name)
{
struct temp_name_list *newp
= (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
char *newname = strdup (name);
if (newname != NULL)
{
newp->name = newname;
if (temp_name_list == NULL)
temp_name_list = (struct temp_name_list *) &newp->q;
else
insque (newp, temp_name_list);
}
else
free (newp);
}
int
create_temp_file (const char *base, char **filename)
{
char *fname;
int fd;
fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base)
+ sizeof ("XXXXXX"));
strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
fd = mkstemp (fname);
if (fd == -1)
{
printf ("cannot open temporary file '%s': %m\n", fname);
free (fname);
return -1;
}
add_temp_file (fname);
if (filename != NULL)
*filename = fname;
else
free (fname);
return fd;
}
/* Helper functions called by the test skeleton follow. */
void
support_set_test_dir (const char *path)
{
test_dir = path;
}
void
support_delete_temp_files (void)
{
while (temp_name_list != NULL)
{
remove (temp_name_list->name);
free (temp_name_list->name);
struct temp_name_list *next
= (struct temp_name_list *) temp_name_list->q.q_forw;
free (temp_name_list);
temp_name_list = next;
}
}
void
support_print_temp_files (FILE *f)
{
if (temp_name_list != NULL)
{
struct temp_name_list *n;
fprintf (f, "temp_files=(\n");
for (n = temp_name_list;
n != NULL;
n = (struct temp_name_list *) n->q.q_forw)
fprintf (f, " '%s'\n", n->name);
fprintf (f, ")\n");
}
}

37
support/temp_file.h Normal file
View File

@@ -0,0 +1,37 @@
/* Declarations for temporary file handling.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef SUPPORT_TEMP_FILE_H
#define SUPPORT_TEMP_FILE_H
#include <sys/cdefs.h>
__BEGIN_DECLS
/* Schedule a temporary file for deletion on exit. */
void add_temp_file (const char *name);
/* Create a temporary file. Return the opened file descriptor on
success, or -1 on failure. Write the file name to *FILENAME if
FILENAME is not NULL. In this case, the caller is expected to free
*FILENAME. */
int create_temp_file (const char *base, char **filename);
__END_DECLS
#endif /* SUPPORT_TEMP_FILE_H */

158
support/test-driver.c Normal file
View File

@@ -0,0 +1,158 @@
/* Main function for test programs.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This file should be included from test cases. It will define a
main function which provides the test wrapper.
It assumes that the test case defines a function
int do_test (void);
and arranges for that function being called under the test wrapper.
The do_test function should return 0 to indicate a passing test, 1
to indicate a failing test, or 77 to indicate an unsupported test.
Other result values could be used to indicate a failing test, but
the result of the expression is passed to exit and exit only
returns the lower 8 bits of its input. A non-zero return with some
values could cause a test to incorrectly be considered passing when
it really failed. For this reason, the function should always
return 0 (EXIT_SUCCESS), 1 (EXIT_FAILURE), or 77
(EXIT_UNSUPPORTED).
The test function may print out diagnostic or warning messages as well
as messages about failures. These messages should be printed to stdout
and not stderr so that the output is properly ordered with respect to
the rest of the glibc testsuite run output.
Several preprocessors macros can be defined before including this
file.
The name of the do_test function can be changed with the
TEST_FUNCTION macro. It must expand to the desired function name.
If the test case needs access to command line parameters, it must
define the TEST_FUNCTION_ARGV macro with the name of the test
function. It must have the following type:
int TEST_FUNCTION_ARGV (int argc, char **argv);
This overrides the do_test default function and is incompatible
with the TEST_FUNCTION macro.
If PREPARE is defined, it must expand to the name of a function of
the type
void PREPARE (int argc, char **);
This function will be called early, after parsing the command line,
but before running the test, in the parent process which acts as
the test supervisor.
If CLEANUP_HANDLER is defined, it must expand to the name of a
function of the type
void CLEANUP_HANDLER (void);
This function will be called from the timeout (SIGALRM) signal
handler.
If EXPECTED_SIGNAL is defined, it must expanded to a constant which
denotes the expected signal number.
If EXPECTED_STATUS is defined, it must expand to the expected exit
status.
If TIMEOUT is defined, it must be positive constant. It overrides
the default test timeout and is measured in seconds.
If TEST_NO_MALLOPT is defined, the test wrapper will not call
mallopt.
Custom command line handling can be implemented by defining the
CMDLINE_OPTION macro (after including the <getopt.h> header; this
requires _GNU_SOURCE to be defined). This macro must expand to a
to a comma-separated list of braced initializers for struct option
from <getopt.h>, with a trailing comma. CMDLINE_PROCESS can be
defined as the name of a function which is called to process these
options. The function is passed the option character/number and
has this type:
void CMDLINE_PROCESS (int);
*/
#include <support/test-driver.h>
#include <string.h>
int
main (int argc, char **argv)
{
struct test_config test_config;
memset (&test_config, 0, sizeof (test_config));
#ifdef PREPARE
test_config.prepare_function = (PREPARE);
#endif
#if defined (TEST_FUNCTION) && defined (TEST_FUNCTON_ARGV)
# error TEST_FUNCTION and TEST_FUNCTION_ARGV cannot be defined at the same time
#endif
#if defined (TEST_FUNCTION)
test_config.test_function = TEST_FUNCTION;
#elif defined (TEST_FUNCTION_ARGV)
test_config.test_function_argv = TEST_FUNCTION_ARGV;
#else
test_config.test_function = do_test;
#endif
#ifdef CLEANUP_HANDLER
test_config.cleanup_function = CLEANUP_HANDLER;
#endif
#ifdef EXPECTED_SIGNAL
test_config.expected_signal = (EXPECTED_SIGNAL);
#endif
#ifdef EXPECTED_STATUS
test_config.expected_status = (EXPECTED_STATUS);
#endif
#ifdef TEST_NO_MALLOPT
test_config.no_mallopt = 1;
#endif
#ifdef TIMEOUT
test_config.timeout = TIMEOUT;
#endif
#ifdef CMDLINE_OPTIONS
struct option options[] =
{
CMDLINE_OPTIONS
{ "direct", no_argument, NULL, OPT_DIRECT },
{ "test-dir", required_argument, NULL, OPT_TESTDIR },
{ NULL, 0, NULL, 0 }
};
test_config.options = &options;
#endif
#ifdef CMDLINE_PROCESS
test_config.cmdline_function = CMDLINE_PROCESS;
#endif
return support_test_main (argc, argv, &test_config);
}

68
support/test-driver.h Normal file
View File

@@ -0,0 +1,68 @@
/* Interfaces for the test driver.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef SUPPORT_TEST_DRIVER_H
#define SUPPORT_TEST_DRIVER_H
#include <sys/cdefs.h>
__BEGIN_DECLS
struct test_config
{
void (*prepare_function) (int argc, char **argv);
int (*test_function) (void);
int (*test_function_argv) (int argc, char **argv);
void (*cleanup_function) (void);
void (*cmdline_function) (int);
const void *options; /* Custom options if not NULL. */
int timeout; /* Test timeout in seconds. */
int expected_status; /* Expected exit status. */
int expected_signal; /* If non-zero, expect termination by signal. */
char no_mallopt; /* Boolean flag to disable mallopt. */
};
enum
{
/* Test exit status which indicates that the feature is
unsupported. */
EXIT_UNSUPPORTED = 77,
/* Default timeout is twenty seconds. Tests should normally
complete faster than this, but if they don't, that's abnormal
(a bug) anyways. */
DEFAULT_TIMEOUT = 20,
/* Used for command line argument parsing. */
OPT_DIRECT = 1000,
OPT_TESTDIR,
};
/* Options provided by the test driver. */
#define TEST_DEFAULT_OPTIONS \
{ "direct", no_argument, NULL, OPT_DIRECT }, \
{ "test-dir", required_argument, NULL, OPT_TESTDIR }, \
/* The directory the test should use for temporary files. */
extern const char *test_dir;
int support_test_main (int argc, char **argv, const struct test_config *);
__END_DECLS
#endif /* SUPPORT_TEST_DRIVER_H */

29
support/write_message.c Normal file
View File

@@ -0,0 +1,29 @@
/* Write a message to standard output.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <string.h>
#include <unistd.h>
void
write_message (const char *message)
{
ssize_t unused __attribute__ ((unused));
unused = write (STDOUT_FILENO, message, strlen (message));
}

38
support/xasprintf.c Normal file
View File

@@ -0,0 +1,38 @@
/* Error-checking wrapper for asprintf.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
char *
xasprintf (const char *format, ...)
{
va_list ap;
va_start (ap, format);
char *result;
if (vasprintf (&result, format, ap) < 0)
{
printf ("error: asprintf: %m\n");
exit (1);
}
va_end (ap);
return result;
}

34
support/xcalloc.c Normal file
View File

@@ -0,0 +1,34 @@
/* Error-checking wrapper for calloc.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void *
xcalloc (size_t n, size_t s)
{
void *p;
p = calloc (n, s);
if (p == NULL)
oom_error ("calloc", n * s);
return p;
}

34
support/xmalloc.c Normal file
View File

@@ -0,0 +1,34 @@
/* Error-checking wrapper for malloc.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void *
xmalloc (size_t n)
{
void *p;
p = malloc (n);
if (p == NULL)
oom_error ("malloc", n);
return p;
}

View File

@@ -0,0 +1,26 @@
/* pthread_barrier_destroy with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_barrier_destroy (pthread_barrier_t *barrier)
{
xpthread_check_return ("pthread_barrier_destroy",
pthread_barrier_destroy (barrier));
}

View File

@@ -0,0 +1,27 @@
/* pthread_barrier_init with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_barrier_init (pthread_barrier_t *barrier,
pthread_barrierattr_t *attr, unsigned int count)
{
xpthread_check_return ("pthread_barrier_init",
pthread_barrier_init (barrier, attr, count));
}

View File

@@ -0,0 +1,28 @@
/* pthread_barrier_wait with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
int
xpthread_barrier_wait (pthread_barrier_t *barrier)
{
int ret = pthread_barrier_wait (barrier);
if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
xpthread_check_return ("pthread_barrier_wait", ret);
return ret == PTHREAD_BARRIER_SERIAL_THREAD;
}

25
support/xpthread_cancel.c Normal file
View File

@@ -0,0 +1,25 @@
/* pthread_cancel with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_cancel (pthread_t thr)
{
xpthread_check_return ("pthread_cancel", pthread_cancel (thr));
}

View File

@@ -0,0 +1,34 @@
/* Return value checking for pthread functions, exit variant.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
void
xpthread_check_return (const char *function, int value)
{
if (value != 0)
{
errno = value;
printf ("error: %s: %m\n", function);
exit (1);
}
}

View File

@@ -0,0 +1,26 @@
/* pthread_cond_wait with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
{
xpthread_check_return
("pthread_cond_wait", pthread_cond_wait (cond, mutex));
}

29
support/xpthread_create.c Normal file
View File

@@ -0,0 +1,29 @@
/* pthread_create with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
pthread_t
xpthread_create (pthread_attr_t *attr,
void *(*thread_func) (void *), void *closure)
{
pthread_t thr;
xpthread_check_return
("pthread_create", pthread_create (&thr, attr, thread_func, closure));
return thr;
}

25
support/xpthread_detach.c Normal file
View File

@@ -0,0 +1,25 @@
/* pthread_detach with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_detach (pthread_t thr)
{
xpthread_check_return ("pthread_detach", pthread_detach (thr));
}

27
support/xpthread_join.c Normal file
View File

@@ -0,0 +1,27 @@
/* pthread_join with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void *
xpthread_join (pthread_t thr)
{
void *result;
xpthread_check_return ("pthread_join", pthread_join (thr, &result));
return result;
}

View File

@@ -0,0 +1,25 @@
/* pthread_mutex_lock with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_mutex_lock (pthread_mutex_t *mutex)
{
xpthread_check_return ("pthread_mutex_lock", pthread_mutex_lock (mutex));
}

View File

@@ -0,0 +1,25 @@
/* pthread_mutex_unlock with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_mutex_unlock (pthread_mutex_t *mutex)
{
xpthread_check_return ("pthread_mutex_unlock", pthread_mutex_unlock (mutex));
}

View File

@@ -0,0 +1,34 @@
/* pthread_sigmask with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xsignal.h>
#include <support/support.h>
#include <unistd.h>
void
xpthread_sigmask (int how, const sigset_t *set, sigset_t *oldset)
{
if (pthread_sigmask (how, set, oldset) != 0)
{
write_message ("error: pthread_setmask failed\n");
/* Do not use exit because pthread_sigmask can be called from a
signal handler. */
_exit (1);
}
}

View File

@@ -0,0 +1,25 @@
/* pthread_spin_lock with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_spin_lock (pthread_spinlock_t *lock)
{
xpthread_check_return ("pthread_spin_lock", pthread_spin_lock (lock));
}

View File

@@ -0,0 +1,25 @@
/* pthread_spin_unlock with error checking.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/xthread.h>
void
xpthread_spin_unlock (pthread_spinlock_t *lock)
{
xpthread_check_return ("pthread_spin_unlock", pthread_spin_unlock (lock));
}

32
support/xrealloc.c Normal file
View File

@@ -0,0 +1,32 @@
/* Error-checking wrapper for realloc.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void *
xrealloc (void *p, size_t n)
{
void *result = realloc (p, n);
if (result == NULL && (n > 0 || p == NULL))
oom_error ("realloc", n);
return result;
}

34
support/xsignal.h Normal file
View File

@@ -0,0 +1,34 @@
/* Support functionality for using signals.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef SUPPORT_SIGNAL_H
#define SUPPORT_SIGNAL_H
#include <signal.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
/* The following functions call the corresponding libpthread functions
and terminate the process on error. */
void xpthread_sigmask (int how, const sigset_t *set, sigset_t *oldset);
__END_DECLS
#endif /* SUPPORT_SIGNAL_H */

61
support/xthread.h Normal file
View File

@@ -0,0 +1,61 @@
/* Support functionality for using threads.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef SUPPORT_THREAD_H
#define SUPPORT_THREAD_H
#include <pthread.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
/* Terminate the process (with exit status 0) after SECONDS have
elapsed, from a helper thread. The process is terminated with the
exit function, so atexit handlers are executed. */
void delayed_exit (int seconds);
/* Terminate the process (with exit status 1) if VALUE is not zero.
In that case, print a failure message to standard output mentioning
FUNCTION. The process is terminated with the exit function, so
atexit handlers are executed. */
void xpthread_check_return (const char *function, int value);
/* The following functions call the corresponding libpthread functions
and terminate the process on error. */
void xpthread_barrier_init (pthread_barrier_t *barrier,
pthread_barrierattr_t *attr, unsigned int count);
void xpthread_barrier_destroy (pthread_barrier_t *barrier);
void xpthread_mutex_lock (pthread_mutex_t *mutex);
void xpthread_mutex_unlock (pthread_mutex_t *mutex);
void xpthread_spin_lock (pthread_spinlock_t *lock);
void xpthread_spin_unlock (pthread_spinlock_t *lock);
void xpthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex);
pthread_t xpthread_create (pthread_attr_t *attr,
void *(*thread_func) (void *), void *closure);
void xpthread_detach (pthread_t thr);
void xpthread_cancel (pthread_t thr);
void *xpthread_join (pthread_t thr);
/* This function returns non-zero if pthread_barrier_wait returned
PTHREAD_BARRIER_SERIAL_THREAD. */
int xpthread_barrier_wait (pthread_barrier_t *barrier);
__END_DECLS
#endif /* SUPPORT_THREAD_H */