about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/tst-clone2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/tst-clone2.c')
-rw-r--r--sysdeps/unix/sysv/linux/tst-clone2.c111
1 files changed, 40 insertions, 71 deletions
diff --git a/sysdeps/unix/sysv/linux/tst-clone2.c b/sysdeps/unix/sysv/linux/tst-clone2.c
index 68a7e6d6e2..0da9e54ba2 100644
--- a/sysdeps/unix/sysv/linux/tst-clone2.c
+++ b/sysdeps/unix/sysv/linux/tst-clone2.c
@@ -28,8 +28,14 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/syscall.h>
 
-#include <tls.h> /* for THREAD_* macros.  */
+#include <stackinfo.h>  /* For _STACK_GROWS_{UP,DOWN}.  */
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include <test-skeleton.c>
 
 static int sig;
 static int pipefd[2];
@@ -39,39 +45,35 @@ f (void *a)
 {
   close (pipefd[0]);
 
-  pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
-  pid_t tid = THREAD_GETMEM (THREAD_SELF, tid);
+  pid_t ppid = getppid ();
+  pid_t pid = getpid ();
+  pid_t tid = syscall (__NR_gettid);
 
-  while (write (pipefd[1], &pid, sizeof pid) < 0)
-    continue;
-  while (write (pipefd[1], &tid, sizeof tid) < 0)
-    continue;
+  if (write (pipefd[1], &ppid, sizeof ppid) != sizeof (ppid))
+    FAIL_EXIT1 ("write ppid failed\n");
+  if (write (pipefd[1], &pid, sizeof pid) != sizeof (pid))
+    FAIL_EXIT1 ("write pid failed\n");
+  if (write (pipefd[1], &tid, sizeof tid) != sizeof (tid))
+    FAIL_EXIT1 ("write tid failed\n");
 
   return 0;
 }
 
 
 static int
-clone_test (int clone_flags)
+do_test (void)
 {
   sig = SIGRTMIN;
   sigset_t ss;
   sigemptyset (&ss);
   sigaddset (&ss, sig);
   if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
-    {
-      printf ("sigprocmask failed: %m\n");
-      return 1;
-    }
+    FAIL_EXIT1 ("sigprocmask failed: %m");
 
   if (pipe2 (pipefd, O_CLOEXEC))
-    {
-      printf ("sigprocmask failed: %m\n");
-      return 1;
-    }
-
-  pid_t ppid = getpid ();
+    FAIL_EXIT1 ("pipe failed: %m");
 
+  int clone_flags = 0;
 #ifdef __ia64__
   extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
 		       size_t __child_stack_size, int __flags,
@@ -88,61 +90,47 @@ clone_test (int clone_flags)
 #error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
 #endif
 #endif
+
   close (pipefd[1]);
 
   if (p == -1)
+    FAIL_EXIT1("clone failed: %m");
+
+  pid_t ppid, pid, tid;
+  if (read (pipefd[0], &ppid, sizeof pid) != sizeof pid)
     {
-      printf ("clone failed: %m\n");
-      return 1;
+      kill (p, SIGKILL);
+      FAIL_EXIT1 ("read ppid failed: %m");
     }
-
-  pid_t pid, tid;
   if (read (pipefd[0], &pid, sizeof pid) != sizeof pid)
     {
-      printf ("read pid failed: %m\n");
       kill (p, SIGKILL);
-      return 1;
+      FAIL_EXIT1 ("read pid failed: %m");
     }
   if (read (pipefd[0], &tid, sizeof tid) != sizeof tid)
     {
-      printf ("read pid failed: %m\n");
       kill (p, SIGKILL);
-      return 1;
+      FAIL_EXIT1 ("read tid failed: %m");
     }
 
   close (pipefd[0]);
 
   int ret = 0;
 
-  /* For CLONE_VM glibc clone implementation does not change the pthread
-     pid/tid field.  */
-  if ((clone_flags & CLONE_VM) == CLONE_VM)
-    {
-      if ((ppid != pid) || (ppid != tid))
-	{
-	  printf ("parent pid (%i) != received pid/tid (%i/%i)\n",
-		  (int)ppid, (int)pid, (int)tid);
-	  ret = 1;
-	}
-    }
-  /* For any other flag clone updates the new pthread pid and tid with
-     the clone return value.  */
-  else
-    {
-      if ((p != pid) || (p != tid))
-	{
-	  printf ("child pid (%i) != received pid/tid (%i/%i)\n",
-		  (int)p, (int)pid, (int)tid);
-	  ret = 1;
-	}
-    }
+  pid_t own_pid = getpid ();
+  pid_t own_tid = syscall (__NR_gettid);
+
+  /* Some sanity checks for clone syscall: returned ppid should be current
+     pid and both returned tid/pid should be different from current one.  */
+  if ((ppid != own_pid) || (pid == own_pid) || (tid == own_tid))
+    FAIL_RET ("ppid=%i pid=%i tid=%i | own_pid=%i own_tid=%i",
+	      (int)ppid, (int)pid, (int)tid, (int)own_pid, (int)own_tid);
 
   int e;
   if (waitpid (p, &e, __WCLONE) != p)
     {
-      puts ("waitpid failed");
       kill (p, SIGKILL);
-      return 1;
+      FAIL_EXIT1 ("waitpid failed");
     }
   if (!WIFEXITED (e))
     {
@@ -150,29 +138,10 @@ clone_test (int clone_flags)
 	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
       else
 	puts ("did not terminate correctly");
-      return 1;
+      exit (EXIT_FAILURE);
     }
   if (WEXITSTATUS (e) != 0)
-    {
-      printf ("exit code %d\n", WEXITSTATUS (e));
-      return 1;
-    }
+    FAIL_EXIT1 ("exit code %d", WEXITSTATUS (e));
 
   return ret;
 }
-
-int
-do_test (void)
-{
-  /* First, check that the clone implementation, without any flag, updates
-     the struct pthread to contain the new PID and TID.  */
-  int ret = clone_test (0);
-  /* Second, check that with CLONE_VM the struct pthread PID and TID fields
-     remain unmodified after the clone.  Any modifications would cause problem
-     for the parent as described in bug 19957.  */
-  ret += clone_test (CLONE_VM);
-  return ret;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"