X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/bf336dc52970daa394d119b11284a1b5016a74c0..898aa30bfb038ffeca54d6dea95f0f80fbc08f7f:/t/errthread.c diff --git a/t/errthread.c b/t/errthread.c index 0f1fdf1..3161cf4 100644 --- a/t/errthread.c +++ b/t/errthread.c @@ -23,14 +23,6 @@ #include "errmsg.h" #include "tap.h" -/* - * Function called from output.c but not needed for error messaging. - */ -const char *cdecl__token_name(unsigned token) -{ - tap_bail_out("stub cdecl__token_name called"); -} - /* * Prior returned value from cdecl_get_error in the main thread. */ @@ -60,46 +52,20 @@ static void check_simple_err(const struct cdecl_error *err, unsigned t, } } -static void thread2_func(void) -{ - const struct cdecl_error *err; - - cdecl__errmsg(CDECL__ENOTYPE); - err = cdecl_get_error(); - - /* - * Ensure that the error returned in this new thread is distinct from - * the error returned in the main thread. - */ - tap_diag("thread[2] err: %p", (void *)err); - tap_result(thread1_err != err, "thread[2] new state"); - - check_simple_err(err, 2, CDECL_ENOPARSE, CDECL__ENOTYPE); - - tap_diag("thread[2] exit"); -} - #if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS #define THREAD_API "posix" #include -static void *thread2(void *p) -{ - thread2_func(); - return 0; -} - -static void run_thread2(void) -{ - pthread_t t; - int err; - - if (!(err = pthread_create(&t, 0, thread2, 0))) - if (!(err = pthread_join(t, 0))) - return; - - tap_bail_out("run_thread2 failed: %s", strerror(err)); -} +#define DEFINE_SIMPLE_THREAD_TEST(run_func, thread_entry_func) \ + static void *run_func##_(void *p) { thread_entry_func(); return 0; } \ + static void run_func(void) \ + { \ + pthread_t t; int err; \ + if (!(err = pthread_create(&t, 0, run_func##_, 0))) \ + if (!(err = pthread_join(t, 0))) \ + return; \ + tap_bail_out("%s failed: %s", #run_func, strerror(err)); \ + } static void check_init_once(void) { @@ -110,21 +76,16 @@ static void check_init_once(void) #define THREAD_API "isoc" #include -static int thread2(void *p) -{ - thread2_func(); - return 0; -} - -static void run_thread2(void) -{ - thrd_t t; - if (thrd_create(&t, thread2, 0) == thrd_success) - if (thrd_join(t, 0) == thrd_success) - return; - - tap_bail_out("run_thread2 failed"); -} +#define DEFINE_SIMPLE_THREAD_TEST(run_func, thread_entry_func) \ + static int run_func##_(void *p) { thread_entry_func(); return 0; } \ + static void run_func(void) \ + { \ + thrd_t t; \ + if (thrd_create(&t, run_func##_, 0) == thrd_success) \ + if (thrd_join(t, 0) == thrd_success) \ + return; \ + tap_bail_out("%s failed", #run_func); \ + } static void check_init_once(void) { @@ -136,30 +97,23 @@ static void check_init_once(void) #define WIN32_LEAN_AND_MEAN #include -static DWORD WINAPI thread2(LPVOID p) -{ - thread2_func(); - return 0; -} - -static void run_thread2(void) -{ - HANDLE h; - DWORD rc; - - if ((h = CreateThread(NULL, 0, thread2, NULL, 0, &rc))) { - do { - if (GetExitCodeThread(h, &rc) && rc != STILL_ACTIVE) { - CloseHandle(h); - return; - } - } while (WaitForSingleObject(h, INFINITE) != WAIT_FAILED); +#define DEFINE_SIMPLE_THREAD_TEST(run_func, thread_entry_func) \ + static DWORD WINAPI run_func##_(LPVOID p) \ + { thread_entry_func(); return 0; } \ + static void run_func(void) \ + { \ + HANDLE h; DWORD rc; \ + if ((h = CreateThread(0, 0, run_func##_, 0, 0, &rc))) do { \ + if (GetExitCodeThread(h, &rc) && rc != STILL_ACTIVE) { \ + CloseHandle(h); \ + return; \ + } \ + } while (WaitForSingleObject(h, INFINITE) != WAIT_FAILED); \ + tap_bail_out("%s failed (%lu)", #run_func, GetLastError()); \ } - tap_bail_out("run_thread2 failed (%lu)", GetLastError()); -} - /* Also include init_once sanity test on Windows */ +#define TEST_W32_NO_DLLMAIN 1 #include "thread-w32.h" HANDLE init_semaphore; @@ -222,13 +176,43 @@ int main(void) #endif #ifdef THREAD_API + +static void thread_result(void) +{ + tap_result(1, "thread runs"); +} +DEFINE_SIMPLE_THREAD_TEST(check_thread_create, thread_result); + +static void err_in_thread(void) +{ + const struct cdecl_error *err; + + cdecl__errmsg(CDECL__ENOTYPE); + err = cdecl_get_error(); + + /* + * Ensure that the error returned in this new thread is distinct from + * the error returned in the main thread. + */ + tap_diag("thread[2] err: %p", (void *)err); + tap_result(thread1_err != err, "thread[2] new state"); + + check_simple_err(err, 2, CDECL_ENOPARSE, CDECL__ENOTYPE); + + tap_diag("thread[2] exit"); +} +DEFINE_SIMPLE_THREAD_TEST(check_err_in_thread, err_in_thread); + int main(void) { size_t test_live_allocations(void); const struct cdecl_error *err; tap_diag("using thread API: " THREAD_API); - tap_plan(10); + tap_plan(11); + + /* Create/join a thread to tickle DllMain on Windows. */ + check_thread_create(); /* Simulate an error in the main thread. */ cdecl__errmsg(CDECL__ENOMEM); @@ -236,7 +220,7 @@ int main(void) tap_diag("thread[1] err: %p", (void *)thread1_err); check_simple_err(thread1_err, 1, CDECL_ENOMEM, CDECL__ENOMEM); - run_thread2(); + check_err_in_thread(); /* * Back in the main thread, the error previously returned by