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 | #define NR_AT_EXIT 32 | 148 | #define NR_AT_EXIT 32 |
| 149 | 149 | ||
| 150 | static int exit_called = 0; | 150 | static struct exit_context { |
| 151 | static int nr_exit = 0; | 151 | int exit_called; |
| 152 | static void (*exitfunc[NR_AT_EXIT])(int, void *); | 152 | int nr_exit; |
| 153 | static void *exitarg[NR_AT_EXIT]; | 153 | void (*exitfunc[NR_AT_EXIT])(int, void *); |
| 154 | void *exitarg[NR_AT_EXIT]; | ||
| 154 | #ifndef CONFIG_TCC_BACKTRACE | 155 | #ifndef CONFIG_TCC_BACKTRACE |
| 155 | static jmp_buf run_jmp_buf; | 156 | jmp_buf run_jmp_buf; |
| 156 | #endif | 157 | #endif |
| 158 | } g_exit_context; | ||
| 157 | 159 | ||
| 158 | static void init_exit(void) | 160 | static void init_exit(void) |
| 159 | { | 161 | { |
| 160 | exit_called = 0; | 162 | struct exit_context *e = &g_exit_context; |
| 161 | nr_exit = 0; | 163 | |
| 164 | e->exit_called = 0; | ||
| 165 | e->nr_exit = 0; | ||
| 162 | } | 166 | } |
| 163 | 167 | ||
| 164 | static void call_exit(int ret) | 168 | static void call_exit(int ret) |
| 165 | { | 169 | { |
| 166 | while (nr_exit--) | 170 | struct exit_context *e = &g_exit_context; |
| 167 | exitfunc[nr_exit](ret, exitarg[nr_exit]); | 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 | static int rt_atexit(void (*function)(void)) | 178 | static int rt_atexit(void (*function)(void)) |
| 171 | { | 179 | { |
| 172 | if (nr_exit < NR_AT_EXIT) { | 180 | struct exit_context *e = &g_exit_context; |
| 173 | exitfunc[nr_exit] = (void (*)(int, void *))function; | 181 | |
| 174 | exitarg[nr_exit++] = NULL; | 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 | return 0; | 185 | return 0; |
| 176 | } | 186 | } |
| 177 | return 1; | 187 | return 1; |
| @@ -179,9 +189,11 @@ static int rt_atexit(void (*function)(void)) · 1 unmodified line | |||
| 179 | 189 | ||
| 180 | static int rt_on_exit(void (*function)(int, void *), void *arg) | 190 | static int rt_on_exit(void (*function)(int, void *), void *arg) |
| 181 | { | 191 | { |
| 182 | if (nr_exit < NR_AT_EXIT) { | 192 | struct exit_context *e = &g_exit_context; |
| 183 | exitfunc[nr_exit] = function; | 193 | |
| 184 | exitarg[nr_exit++] = arg; | 194 | if (e->nr_exit < NR_AT_EXIT) { |
| 195 | e->exitfunc[e->nr_exit] = function; | ||
| 196 | e->exitarg[e->nr_exit++] = arg; | ||
| 185 | return 0; | 197 | return 0; |
| 186 | } | 198 | } |
| 187 | return 1; | 199 | return 1; |
| @@ -189,11 +201,13 @@ static int rt_on_exit(void (*function)(int, void *), void *arg) · 1 unmodified line | |||
| 189 | 201 | ||
| 190 | static void run_exit(int code) | 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 | #ifdef CONFIG_TCC_BACKTRACE | 207 | #ifdef CONFIG_TCC_BACKTRACE |
| 194 | longjmp(g_rtctxt.jmp_buf, code ? code : 256); | 208 | longjmp((&g_rtctxt)->jmp_buf, code ? code : 256); |
| 195 | #else | 209 | #else |
| 196 | longjmp(run_jmp_buf, code ? code : 256); | 210 | longjmp(e->run_jmp_buf, code ? code : 256); |
| 197 | #endif | 211 | #endif |
| 198 | } | 212 | } |
| 199 | 213 | ||
| @@ -277,7 +291,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 77 unmodified lines | |||
| 277 | #ifdef CONFIG_TCC_BACKTRACE | 291 | #ifdef CONFIG_TCC_BACKTRACE |
| 278 | if (!(ret = setjmp(rc->jmp_buf))) | 292 | if (!(ret = setjmp(rc->jmp_buf))) |
| 279 | #else | 293 | #else |
| 280 | if (!(ret = setjmp(run_jmp_buf))) | 294 | if (!(ret = setjmp((&g_exit_context)->run_jmp_buf))) |
| 281 | #endif | 295 | #endif |
| 282 | { | 296 | { |
| 283 | ret = prog_main(argc, argv, envp); | 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 | call_exit(ret); | 300 | call_exit(ret); |
| 287 | if ((s1->dflag & 16) && ret) | 301 | if ((s1->dflag & 16) && ret) |
| 288 | fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp); | 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 | exit(ret); | 304 | exit(ret); |
| 291 | return ret; | 305 | return ret; |
| 292 | } | 306 | } |
| @@ -288,6 +288,9 @@ int main(int argc, char **argv) · 287 unmodified lines | |||
| 288 | 288 | ||
| 289 | #else | 289 | #else |
| 290 | #include <tcclib.h> | 290 | #include <tcclib.h> |
| 291 | |||
| 292 | unsigned int sleep(unsigned int seconds); | ||
| 293 | |||
| 291 | int fib(n) | 294 | int fib(n) |
| 292 | { | 295 | { |
| 293 | return (n <= 2) ? 1 : fib(n-1) + fib(n-2); | 296 | return (n <= 2) ? 1 : fib(n-1) + fib(n-2); |
| @@ -295,7 +298,8 @@ int fib(n) · 1 unmodified line | |||
| 295 | 298 | ||
| 296 | int main(int argc, char **argv) | 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 | return 0; | 303 | return 0; |
| 300 | } | 304 | } |
| 301 | #endif | 305 | #endif |