From eac6ee518dd7b42b7d202ee2c7c37e953a44341a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 22:32:32 +0200 Subject: [PATCH] Fixed various memory and logic errors --- src/core/runner.c | 86 +++++++++++++++++++++++++++++++++-------------- src/core/stats.c | 1 + src/core/worker.c | 8 ++++- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index 67b5fad..3817bc6 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -296,26 +296,15 @@ static void handle_event(struct event *ev) { static struct process *run_test(struct criterion_global_stats *stats, struct criterion_suite_stats *suite_stats, - struct criterion_test *test, - struct criterion_suite *suite, + struct criterion_test_stats *test_stats, struct test_single_param *param) { - struct criterion_test_stats *test_stats = test_stats_init(test); - - if (is_disabled(test, suite)) { - stat_push_event(stats, - suite_stats, - test_stats, - &(struct event) { .kind = PRE_INIT }); - return NULL; - } - struct execution_context ctx = { - .stats = stats, - .test = test, - .test_stats = test_stats, - .suite = suite, - .suite_stats = suite_stats, + .stats = sref(stats), + .test = test_stats->test, + .test_stats = sref(test_stats), + .suite = suite_stats->suite, + .suite_stats = sref(suite_stats), .param = param, }; return spawn_test_worker(&ctx, run_test_child, g_worker_pipe); @@ -362,6 +351,7 @@ static struct process *run_next_test(struct criterion_test_set *p_set, struct criterion_suite_set *suite_set; struct criterion_test *test; struct criterion_suite_stats *suite_stats; + struct criterion_test_stats *test_stats; struct criterion_test_set *set; struct criterion_global_stats *stats; struct criterion_test_params params; @@ -397,8 +387,20 @@ static struct process *run_next_test(struct criterion_test_set *p_set, if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED && ctx->test->data->param_) { + if (is_disabled(ctx->test, ctx->suite_stats->suite)) { + ctx->test_stats = test_stats_init(ctx->test); + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = PRE_INIT }); + sfree(ctx->test_stats); + continue; + } + ctx->params = ctx->test->data->param_(); for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { + ctx->test_stats = test_stats_init(ctx->test); + struct test_single_param param = { ctx->params.size, (char *) ctx->params.params + ctx->i * ctx->params.size @@ -406,12 +408,12 @@ static struct process *run_next_test(struct criterion_test_set *p_set, struct process *worker = run_test(ctx->stats, ctx->suite_stats, - ctx->test, - &ctx->suite_set->suite, + ctx->test_stats, ¶m); if (!is_runner()) { sfree(ctx->suite_stats); + sfree(ctx->test_stats); ccrReturn(NULL); } @@ -421,12 +423,24 @@ static struct process *run_next_test(struct criterion_test_set *p_set, if (ctx->params.cleanup) ctx->params.cleanup(&ctx->params); } else { + ctx->test_stats = test_stats_init(ctx->test); + + if (is_disabled(ctx->test, ctx->suite_stats->suite)) { + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = PRE_INIT }); + sfree(ctx->test_stats); + continue; + } + struct process *worker = run_test(ctx->stats, ctx->suite_stats, - ctx->test, - &ctx->suite_set->suite, + ctx->test_stats, NULL); + sfree(ctx->test_stats); + if (!is_runner()) { sfree(ctx->suite_stats); ccrReturn(NULL); @@ -453,34 +467,54 @@ static void run_tests_async(struct criterion_test_set *set, size_t nb_workers = 1; struct worker_set workers = { .max_workers = nb_workers, - .workers = malloc(sizeof (struct process*) * nb_workers), + .workers = calloc(nb_workers, sizeof (struct process*)), }; size_t active_workers = 0; + FILE *event_pipe = pipe_in(g_worker_pipe, PIPE_DUP); + struct event *ev = NULL; + // initialization of coroutine run_next_test(set, stats, &ctx); for (size_t i = 0; i < nb_workers; ++i) { workers.workers[i] = run_next_test(NULL, NULL, &ctx); + if (!is_runner()) + goto cleanup; + + if (!ctx) + break; ++active_workers; } - FILE *event_pipe = pipe_in(g_worker_pipe, PIPE_DUP); + if (!active_workers) + goto cleanup; - struct event *ev; while ((ev = worker_read_event(&workers, event_pipe)) != NULL) { handle_event(ev); + size_t wi = ev->worker_index; if (ev->kind == WORKER_TERMINATED) { - workers.workers[ev->worker_index] = run_next_test(NULL, NULL, &ctx); - if (workers.workers[ev->worker_index] == NULL) + sfree(workers.workers[wi]); + workers.workers[wi] = ctx ? run_next_test(NULL, NULL, &ctx) : NULL; + + if (!is_runner()) + goto cleanup; + + if (workers.workers[wi] == NULL) --active_workers; } sfree(ev); if (!active_workers) break; } + ev = NULL; +cleanup: + fclose(event_pipe); + sfree(ev); + free(workers.workers); + ccrAbort(ctx); } static int criterion_run_all_tests_impl(struct criterion_test_set *set) { diff --git a/src/core/stats.c b/src/core/stats.c index a9dbe95..488aa5c 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -72,6 +72,7 @@ static void destroy_stats(void *ptr, UNUSED void *meta) { s_glob_stats *stats_init(void) { s_glob_stats *stats = smalloc( .size = sizeof (s_glob_stats), + .kind = SHARED, .dtor = destroy_stats ); *stats = (s_glob_stats) { .suites = NULL }; diff --git a/src/core/worker.c b/src/core/worker.c index 1dd6861..e956176 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -49,6 +49,9 @@ bool is_runner(void) { static void close_process(void *ptr, UNUSED void *meta) { struct process *proc = ptr; fclose(proc->in); + sfree(proc->ctx.suite_stats); + sfree(proc->ctx.test_stats); + sfree(proc->ctx.stats); sfree(proc->proc); } @@ -102,12 +105,15 @@ struct process *spawn_test_worker(struct execution_context *ctx, abort(); } else if (proc == NULL) { run_worker(&g_worker_context); + sfree(ctx->test_stats); + sfree(ctx->suite_stats); + sfree(ctx->stats); return NULL; } ptr = smalloc( .size = sizeof (struct process), - .kind = UNIQUE, + .kind = SHARED, .dtor = close_process); *ptr = (struct process) {