The test failed because atexit/on_exit code was not correct. Make it look more like the g_exit_context. Added a sleep to libtcc_test_mt to allow overlap of threads to detect this problem.
Unified · Split
| @@ -147,31 +147,41 @@ static void run_cdtors(TCCState *s1, const char *start, const char *end, · 146 unmodified lines | ||
| 147 | 147 | |
| 148 | 148 | #define NR_AT_EXIT 32 |
| 149 | 149 | |
| 150 | −static int exit_called = 0; | |
| 151 | −static int nr_exit = 0; | |
| 152 | −static void (*exitfunc[NR_AT_EXIT])(int, void *); | |
| 153 | −static void *exitarg[NR_AT_EXIT]; | |
| 150 | +static struct exit_context { | |
| 151 | + int exit_called; | |
| 152 | + int nr_exit; | |
| 153 | + void (*exitfunc[NR_AT_EXIT])(int, void *); | |
| 154 | + void *exitarg[NR_AT_EXIT]; | |
| 154 | 155 | #ifndef CONFIG_TCC_BACKTRACE |
| 155 | −static jmp_buf run_jmp_buf; | |
| 156 | + jmp_buf run_jmp_buf; | |
| 156 | 157 | #endif |
| 158 | +} g_exit_context; | |
| 157 | 159 | |
| 158 | 160 | static void init_exit(void) |
| 159 | 161 | { |
| 160 | − exit_called = 0; | |
| 161 | − nr_exit = 0; | |
| 162 | + struct exit_context *e = &g_exit_context; | |
| 163 | + | |
| 164 | + e->exit_called = 0; | |
| 165 | + e->nr_exit = 0; | |
| 162 | 166 | } |
| 163 | 167 | |
| 164 | 168 | static void call_exit(int ret) |
| 165 | 169 | { |
| 166 | − while (nr_exit--) | |
| 167 | − exitfunc[nr_exit](ret, exitarg[nr_exit]); | |
| 170 | + struct exit_context *e = &g_exit_context; | |
| 171 | + | |
| 172 | + while (e->nr_exit) { | |
| 173 | + e->nr_exit--; | |
| 174 | + e->exitfunc[e->nr_exit](ret, e->exitarg[e->nr_exit]); | |
| 175 | + } | |
| 168 | 176 | } |
| 169 | 177 | |
| 170 | 178 | static int rt_atexit(void (*function)(void)) |
| 171 | 179 | { |
| 172 | − if (nr_exit < NR_AT_EXIT) { | |
| 173 | − exitfunc[nr_exit] = (void (*)(int, void *))function; | |
| 174 | − exitarg[nr_exit++] = NULL; | |
| 180 | + struct exit_context *e = &g_exit_context; | |
| 181 | + | |
| 182 | + if (e->nr_exit < NR_AT_EXIT) { | |
| 183 | + e->exitfunc[e->nr_exit] = (void (*)(int, void *))function; | |
| 184 | + e->exitarg[e->nr_exit++] = NULL; | |
| 175 | 185 | return 0; |
| 176 | 186 | } |
| 177 | 187 | return 1; |
| @@ -179,9 +189,11 @@ static int rt_atexit(void (*function)(void)) · 1 unmodified line | ||
| 179 | 189 | |
| 180 | 190 | static int rt_on_exit(void (*function)(int, void *), void *arg) |
| 181 | 191 | { |
| 182 | − if (nr_exit < NR_AT_EXIT) { | |
| 183 | − exitfunc[nr_exit] = function; | |
| 184 | − exitarg[nr_exit++] = arg; | |
| 192 | + struct exit_context *e = &g_exit_context; | |
| 193 | + | |
| 194 | + if (e->nr_exit < NR_AT_EXIT) { | |
| 195 | + e->exitfunc[e->nr_exit] = function; | |
| 196 | + e->exitarg[e->nr_exit++] = arg; | |
| 185 | 197 | return 0; |
| 186 | 198 | } |
| 187 | 199 | return 1; |
| @@ -189,11 +201,13 @@ static int rt_on_exit(void (*function)(int, void *), void *arg) · 1 unmodified line | ||
| 189 | 201 | |
| 190 | 202 | static void run_exit(int code) |
| 191 | 203 | { |
| 192 | − exit_called = 1; | |
| 204 | + struct exit_context *e = &g_exit_context; | |
| 205 | + | |
| 206 | + e->exit_called = 1; | |
| 193 | 207 | #ifdef CONFIG_TCC_BACKTRACE |
| 194 | − longjmp(g_rtctxt.jmp_buf, code ? code : 256); | |
| 208 | + longjmp((&g_rtctxt)->jmp_buf, code ? code : 256); | |
| 195 | 209 | #else |
| 196 | − longjmp(run_jmp_buf, code ? code : 256); | |
| 210 | + longjmp(e->run_jmp_buf, code ? code : 256); | |
| 197 | 211 | #endif |
| 198 | 212 | } |
| 199 | 213 | |
| @@ -277,7 +291,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 77 unmodified lines | ||
| 277 | 291 | #ifdef CONFIG_TCC_BACKTRACE |
| 278 | 292 | if (!(ret = setjmp(rc->jmp_buf))) |
| 279 | 293 | #else |
| 280 | − if (!(ret = setjmp(run_jmp_buf))) | |
| 294 | + if (!(ret = setjmp((&g_exit_context)->run_jmp_buf))) | |
| 281 | 295 | #endif |
| 282 | 296 | { |
| 283 | 297 | ret = prog_main(argc, argv, envp); |
| @@ -286,7 +300,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 2 unmodified lines | ||
| 286 | 300 | call_exit(ret); |
| 287 | 301 | if ((s1->dflag & 16) && ret) |
| 288 | 302 | fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp); |
| 289 | − if ((s1->dflag & 16) == 0 && exit_called) | |
| 303 | + if ((s1->dflag & 16) == 0 && (&g_exit_context)->exit_called) | |
| 290 | 304 | exit(ret); |
| 291 | 305 | return ret; |
| 292 | 306 | } |
| @@ -288,6 +288,9 @@ int main(int argc, char **argv) · 287 unmodified lines | ||
| 288 | 288 | |
| 289 | 289 | #else |
| 290 | 290 | #include <tcclib.h> |
| 291 | + | |
| 292 | +unsigned int sleep(unsigned int seconds); | |
| 293 | + | |
| 291 | 294 | int fib(n) |
| 292 | 295 | { |
| 293 | 296 | return (n <= 2) ? 1 : fib(n-1) + fib(n-2); |
| @@ -295,7 +298,8 @@ int fib(n) · 1 unmodified line | ||
| 295 | 298 | |
| 296 | 299 | int main(int argc, char **argv) |
| 297 | 300 | { |
| 298 | − printf(" %d", fib(atoi(argv[1]), 2)); | |
| 301 | + sleep(1); | |
| 302 | + printf(" %d", fib(atoi(argv[1]))); | |
| 299 | 303 | return 0; |
| 300 | 304 | } |
| 301 | 305 | #endif |