raise (signo);
}
-static void child_pause (void)
+static __attribute__((__noreturn__)) void child_pause (void)
{
for (;;)
pause ();
raise (SIGALRM);
}
-static void child_alrm (void)
+static __attribute__((__noreturn__)) void child_alrm (void)
{
void (*handler_orig) (int signo);
#if 0
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;
return pass (data, input);
}
-static void *spawn_threaded_parent_start (void *arg)
+static __attribute__((__noreturn__)) void *spawn_threaded_parent_start (void *arg)
{
for (;;)
pause ();
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),
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;
do
{
+ pid_t pid_threaded, pid_threaded_got;
+ int status;
+
while (loops_print > 0)
{
printf ("%lu\n", loops);
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;
}