aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2017-08-29 10:42:42 -0700
committerPaul Pluzhnikov <ppluzhnikov@google.com>2017-08-29 10:46:44 -0700
commit8325b477b14353aa62192d0fdc7e883e5ced75d1 (patch)
tree91c3fd0be907739330389d163ee580b940b9fd9b /stdlib
parent319cbbf633ae60d7b4b89fcbb11a734f4d7d22f0 (diff)
downloadglibc-8325b477b14353aa62192d0fdc7e883e5ced75d1.zip
glibc-8325b477b14353aa62192d0fdc7e883e5ced75d1.tar.gz
glibc-8325b477b14353aa62192d0fdc7e883e5ced75d1.tar.bz2
2017-08-29 Paul Pluzhnikov <ppluzhnikov@google.com>
* stdlib/tst-atexit-common.c (do_test): Test handler inheritance by child.
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/tst-atexit-common.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/stdlib/tst-atexit-common.c b/stdlib/tst-atexit-common.c
index 262235a..99b00bf 100644
--- a/stdlib/tst-atexit-common.c
+++ b/stdlib/tst-atexit-common.c
@@ -21,11 +21,20 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/wait.h>
#define MAX_ATEXIT 20 /* Large enough for current set of invocations. */
static char crumbs[MAX_ATEXIT];
static int next_slot = 0;
+/* Helper: flush stdout and _exit. */
+static void
+_exit_with_flush (int code)
+{
+ fflush (stdout);
+ _exit (code);
+}
+
static void
fn0 (void)
{
@@ -60,11 +69,11 @@ fn_final (void)
const char expected[] = "3021121130211";
if (strcmp (crumbs, expected) == 0)
- _exit (0);
+ _exit_with_flush (0);
printf ("crumbs: %s\n", crumbs);
printf ("expected: %s\n", expected);
- _exit (1);
+ _exit_with_flush (1);
}
/* This is currently just a basic test to verify that exit handlers execute
@@ -72,8 +81,7 @@ fn_final (void)
TODO: Additional tests that we should do:
1. POSIX says we need to support at least ATEXIT_MAX
- 2. Verify that fork'd child inherit the registrations of the parent.
- 3. ... */
+ 2. ... */
static int
do_test (void)
@@ -88,6 +96,40 @@ do_test (void)
ATEXIT (fn1);
ATEXIT (fn3);
+ /* Verify that handlers registered above are inherited across fork. */
+ const pid_t child = fork ();
+ switch (child)
+ {
+ case -1:
+ printf ("fork: %m\n");
+ _exit_with_flush (3);
+ case 0: /* Child. */
+ break;
+ default:
+ {
+ int status;
+ const pid_t exited = waitpid (child, &status, 0);
+ if (child != exited)
+ {
+ printf ("unexpected child: %d, expected %d\n", exited, child);
+ _exit_with_flush (4);
+ }
+ if (status != 0)
+ {
+ if (WIFEXITED (status))
+ printf ("unexpected exit status %d from child %d\n",
+ WEXITSTATUS (status), child);
+ else if (WIFSIGNALED (status))
+ printf ("unexpected signal %d from child %d\n",
+ WTERMSIG (status), child);
+ else
+ printf ("unexpected status %d from child %d\n", status, child);
+ _exit_with_flush (5);
+ }
+ }
+ break;
+ }
+
EXIT (2); /* If we see this exit code, fn_final must have not worked. */
}