blob: d32a9bfe0f0f6e7a3290949b1e6270914c7522f9 [file] [log] [blame]
/* Copyright (c) 2016 Google, Inc.
* Barret Rhoden <brho@cs.berkeley.edu>
* See LICENSE for details. */
#include <utest/utest.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
/* This tests a bug where if a thread other than thread0 registered an atexit()
* function, we'd GPF when thread0 exited. Due to the way our infrastructure
* prints tests results before the program exited, you may see this say that the
* test succeeded, but then fail later with a GPF or other assertion. */
TEST_SUITE("AT-EXIT");
/* <--- Begin definition of test cases ---> */
static bool child_ran_atexit = FALSE;
static void child_atexit(void)
{
child_ran_atexit = TRUE;
}
static void *child_func(void *arg)
{
atexit(child_atexit);
return 0;
}
static void main_atexit(void)
{
/* Using the non-UT assert, since the test_atexit_threads() has already
* returned. Also, since the child called atexit() after main, its
* handler should run first, according to the man page. */
assert(child_ran_atexit);
}
bool test_atexit_threads(void)
{
pthread_t child;
void *child_ret;
atexit(main_atexit);
pthread_create(&child, NULL, &child_func, NULL);
pthread_join(child, &child_ret);
return TRUE;
}
/* <--- End definition of test cases ---> */
struct utest utests[] = {
UTEST_REG(atexit_threads),
};
int num_utests = sizeof(utests) / sizeof(struct utest);
int main(int argc, char *argv[])
{
char **whitelist = &argv[1];
int whitelist_len = argc - 1;
RUN_TEST_SUITE(utests, num_utests, whitelist, whitelist_len);
}