about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--stdlib/tst-atexit-common.c50
2 files changed, 51 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index ce754281b3..e78518a693 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2017-08-29  Paul Pluzhnikov  <ppluzhnikov@google.com>
+
+	* stdlib/tst-atexit-common.c (do_test): Test handler inheritance
+	by child.
+
 2017-08-29  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 	    Aurelien Jarno  <aurelien@aurel32.net>
 	    Maciej W. Rozycki  <macro@imgtec.com>
diff --git a/stdlib/tst-atexit-common.c b/stdlib/tst-atexit-common.c
index 262235a478..99b00bf3aa 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.  */
 }