Resolve race with libpthread initialization.
authorlace <>
Wed, 16 May 2007 18:05:16 +0000 (18:05 +0000)
committerlace <>
Wed, 16 May 2007 18:05:16 +0000 (18:05 +0000)
Mark some functions as NORETURN.

testsuite.c

index bcf81d1..065d0a9 100644 (file)
@@ -138,7 +138,7 @@ static void registry_handler (int signo)
   raise (signo);
 }
 
-static void child_pause (void)
+static __attribute__((__noreturn__)) void child_pause (void)
 {
   for (;;)
     pause ();
@@ -152,7 +152,7 @@ static void child_alrm_handler (int signo)
   raise (SIGALRM);
 }
 
-static void child_alrm (void)
+static __attribute__((__noreturn__)) void child_alrm (void)
 {
   void (*handler_orig) (int signo);
 #if 0
@@ -243,7 +243,7 @@ struct child_spawner
     int fd;
   };
 
-static void *child_spawner (void *param_voidpointer, void *input)
+static __attribute__((__noreturn__)) void *child_spawner (void *param_voidpointer, void *input)
 {
   struct child_spawner *param = param_voidpointer;
   pid_t inferior;
@@ -413,7 +413,7 @@ static void *spawn_singlethreaded (void *data, void *input)
   return pass (data, input);
 }
 
-static void *spawn_threaded_parent_start (void *arg)
+static __attribute__((__noreturn__)) void *spawn_threaded_parent_start (void *arg)
 {
   for (;;)
     pause ();
@@ -421,81 +421,82 @@ static void *spawn_threaded_parent_start (void *arg)
   abort ();
 }
 
+static void *libpthread_handle;
+static int (*libpthread_create_pointer) (pthread_t *thread,
+                                        const pthread_attr_t *attr,
+                                        void *(*start_routine) (void *),
+                                        void *arg);
+static int (*libpthread_join_pointer) (pthread_t thread, void **value_ptr);
+
+static void libpthread_open (void)
+{
+  assert (libpthread_handle == NULL);
+
+  libpthread_handle = dlopen ("libpthread.so.0", RTLD_LAZY);
+  assert (libpthread_handle != NULL);
+
+  libpthread_create_pointer = dlsym (libpthread_handle, "pthread_create");
+  assert (libpthread_create_pointer != NULL);
+  libpthread_join_pointer = dlsym (libpthread_handle, "pthread_join");
+  assert (libpthread_join_pointer != NULL);
+
+}
+
+static void libpthread_close (void)
+{
+  int i;
+
+  assert (libpthread_handle != NULL);
+
+  i = dlclose (libpthread_handle);
+  assert (i == 0);
+  libpthread_handle = NULL;
+}
+
 static void *spawn_threaded_parent (void *data, void *input)
 {
   pthread_t thread;
   int i;
-  void *handle;
-  void *retval;
-  int (*pthread_create_pointer) (pthread_t *thread,
-                                const pthread_attr_t *attr,
-                                void *(*start_routine) (void *),
-                                void *arg);
-
-  handle = dlopen ("libpthread.so.0", RTLD_LAZY);
-  assert (handle != NULL);
-  pthread_create_pointer = dlsym (handle, "pthread_create");
-  assert (pthread_create_pointer != NULL);
-
-  i = (*pthread_create_pointer) (&thread, NULL, spawn_threaded_parent_start,
-                                NULL);
-  assert (i == 0);
-  retval = pass (data, input);
 
-  i = dlclose (handle);
+  assert (libpthread_create_pointer != NULL);
+  i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_parent_start,
+                                   NULL);
   assert (i == 0);
-
-  return retval;
+  return pass (data, input);
 }
 
 struct spawn_threaded_child_start
   {
     void *data;
     void *input;
-    void *lib_handle;
   };
 
 static void *spawn_threaded_child_start (void *arg_voidpointer)
 {
   struct spawn_threaded_child_start *arg = arg_voidpointer;
-  void *retval;
-  int i;
 
-  retval = pass (arg->data, arg->input);
-
-  i = dlclose (arg->lib_handle);
-  assert (i == 0);
-
-  return retval;
+  return pass (arg->data, arg->input);
 }
 
-static void *spawn_threaded_child (void *data, void *input)
+static __attribute__((__noreturn__)) void *spawn_threaded_child (void *data, void *input)
 {
   pthread_t thread;
   int i;
   struct spawn_threaded_child_start arg_local;
-  int (*pthread_create_pointer) (pthread_t *thread,
-                                const pthread_attr_t *attr,
-                                void *(*start_routine) (void *),
-                                void *arg);
-  int (*pthread_join_pointer) (pthread_t thread, void **value_ptr);
-
-  arg_local.lib_handle = dlopen ("libpthread.so.0", RTLD_LAZY);
-  assert (arg_local.lib_handle != NULL);
-  pthread_create_pointer = dlsym (arg_local.lib_handle, "pthread_create");
-  assert (pthread_create_pointer != NULL);
-  pthread_join_pointer = dlsym (arg_local.lib_handle, "pthread_join");
-  assert (pthread_join_pointer != NULL);
 
   arg_local.data = data;
   arg_local.input = input;
-  i = (*pthread_create_pointer) (&thread, NULL, spawn_threaded_child_start,
-                                &arg_local);
+  assert (libpthread_create_pointer != NULL);
+  i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_child_start,
+                                   &arg_local);
   assert (i == 0);
-  i = (*pthread_join_pointer) (thread, NULL);
+  assert (libpthread_join_pointer != NULL);
+  i = (*libpthread_join_pointer) (thread, NULL);
   assert (i == 0);
 
   _exit (EXIT_SUCCESS);
+  /* NOTREACHED */
+  abort ();
 }
 
 static void body_maywaiter (void *(*child) (void *data, void *input),
@@ -519,6 +520,24 @@ static void handler_sigusr1 (int signo)
   loops_print++;
 }
 
+static __attribute__((__noreturn__)) void *tests_threaded (void *data, void *input)
+{
+  libpthread_open ();
+
+  spawned_threads_count = 2;
+  body_maywaiter (spawn_threaded_parent, NULL, NULL);
+
+  spawned_threads_count = 2;
+  body_maywaiter (spawn_threaded_child, NULL, NULL);
+
+  libpthread_close ();
+
+  registry_cleanup ();
+  _exit (EXIT_SUCCESS);
+  /* NOTREACHED */
+  abort ();
+}
+
 int main (int argc, char **argv)
 {
   int loop = 0;
@@ -547,6 +566,9 @@ int main (int argc, char **argv)
 
   do
     {
+      pid_t pid_threaded, pid_threaded_got;
+      int status;
+
       while (loops_print > 0)
         {
          printf ("%lu\n", loops);
@@ -556,16 +578,21 @@ int main (int argc, char **argv)
       spawned_threads_count = 0;
       body_maywaiter (spawn_singlethreaded, NULL, NULL);
 
-      spawned_threads_count = 2;
-      body_maywaiter (spawn_threaded_parent, NULL, NULL);
-
-      spawned_threads_count = 2;
-      body_maywaiter (spawn_threaded_child, NULL, NULL);
+      /* We cannot rely on LIBPTHREAD_CLOSE as libpthread would be still loaded
+         with ATTACH_STATE_REDELIVERED_GET () reporting 1 for
+         SPAWN_SINGLETHREADED.  */
+      pid_threaded = spawn (tests_threaded, NULL, NULL, -1);
+      pid_threaded_got = waitpid (pid_threaded, &status, 0);
+      assert (pid_threaded_got == pid_threaded);
+      assert (WIFEXITED (status) && WEXITSTATUS (status) == 0);
+      STATE (pid_threaded, 1 << STATE_ENOENT);
+      registry_remove (pid_threaded);
 
       registry_cleanup ();
       loops++;
     }
-  while (loop != 0);
+  /* Run at least twice to test libpthread_close ().  */
+  while (loop != 0 || loops == 1);
 
   return EXIT_SUCCESS;
 }