threadleak.c raw
1
2 #ifdef HAVE_CONFIG_H
3 # include "config.h"
4 #endif
5
6 #ifndef GC_THREADS
7 # define GC_THREADS
8 #endif
9
10 #undef GC_NO_THREAD_REDIRECTS
11 #include "gc/leak_detector.h"
12
13 #ifdef GC_PTHREADS
14 # include <errno.h> /*< for `EAGAIN` */
15 # include <pthread.h>
16 #else
17 # ifndef WIN32_LEAN_AND_MEAN
18 # define WIN32_LEAN_AND_MEAN 1
19 # endif
20 # define NOSERVICE
21 # include <windows.h>
22 #endif /* !GC_PTHREADS */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #define N_TESTS 100
28
29 #define CHECK_OUT_OF_MEMORY(p) \
30 do { \
31 if (NULL == (p)) { \
32 fprintf(stderr, "Out of memory\n"); \
33 exit(69); \
34 } \
35 } while (0)
36
37 #ifdef GC_PTHREADS
38 static void *
39 test(void *arg)
40 #else
41 static DWORD WINAPI
42 test(LPVOID arg)
43 #endif
44 {
45 int *p[N_TESTS];
46 int i;
47 for (i = 0; i < N_TESTS; ++i) {
48 p[i] = (int *)malloc(sizeof(int) + i);
49 CHECK_OUT_OF_MEMORY(p[i]);
50 }
51 CHECK_LEAKS();
52 for (i = 1; i < N_TESTS; ++i) {
53 free(p[i]);
54 }
55 #ifdef GC_PTHREADS
56 return arg;
57 #else
58 return (DWORD)(GC_uintptr_t)arg;
59 #endif
60 }
61
62 #ifndef NTHREADS
63 # define NTHREADS 5
64 #endif
65
66 int
67 main(void)
68 {
69 #if NTHREADS > 0
70 int i, n;
71 # ifdef GC_PTHREADS
72 pthread_t t[NTHREADS];
73 # else
74 HANDLE t[NTHREADS];
75 # endif
76 #endif
77
78 #ifndef NO_FIND_LEAK
79 /* Just in case the code is compiled without `FIND_LEAK` macro defined. */
80 GC_set_find_leak(1);
81 #endif
82 GC_INIT();
83 /* This is optional if `pthread_create()` is redirected. */
84 GC_allow_register_threads();
85
86 #if NTHREADS > 0
87 for (i = 0; i < NTHREADS; ++i) {
88 # ifdef GC_PTHREADS
89 int err = pthread_create(t + i, 0, test, 0);
90
91 if (err != 0) {
92 fprintf(stderr, "Thread #%d creation failed, errno= %d\n", i, err);
93 if (i > 1 && EAGAIN == err)
94 break;
95 exit(2);
96 }
97 # else
98 DWORD thread_id;
99
100 t[i] = CreateThread(NULL, 0, test, 0, 0, &thread_id);
101 if (NULL == t[i]) {
102 fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", i,
103 (int)GetLastError());
104 exit(2);
105 }
106 # endif
107 }
108 n = i;
109 for (i = 0; i < n; ++i) {
110 int err;
111
112 # ifdef GC_PTHREADS
113 err = pthread_join(t[i], 0);
114 # else
115 err = WaitForSingleObject(t[i], INFINITE) == WAIT_OBJECT_0
116 ? 0
117 : (int)GetLastError();
118 # endif
119 if (err != 0) {
120 fprintf(stderr, "Thread #%d join failed, errcode= %d\n", i, err);
121 exit(2);
122 }
123 }
124 #else
125 (void)test(NULL);
126 #endif
127
128 CHECK_LEAKS();
129 CHECK_LEAKS();
130 CHECK_LEAKS();
131 printf("SUCCEEDED\n");
132 return 0;
133 }
134