From 8f706b21f36c5cd786dd34ae3eb6b5be5d6e5be2 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Thu, 3 Sep 2020 15:59:35 -0700 Subject: [PATCH] Ref (#284) * rework ref-counting and async shutdown for a number of core types and their dependents --- .tsan_suppressions.txt | 5 +++ bin/elasticurl/main.c | 41 ++++++---------------- source/connection.c | 5 ++- source/connection_manager.c | 4 ++- tests/proxy_test_helper.c | 33 +++++------------- tests/proxy_test_helper.h | 5 ++- tests/test_connection.c | 61 ++++++++++----------------------- tests/test_connection_manager.c | 56 ++++++------------------------ tests/test_tls.c | 36 ++++++++++--------- 9 files changed, 80 insertions(+), 166 deletions(-) create mode 100644 .tsan_suppressions.txt diff --git a/.tsan_suppressions.txt b/.tsan_suppressions.txt new file mode 100644 index 000000000..16f86ac9a --- /dev/null +++ b/.tsan_suppressions.txt @@ -0,0 +1,5 @@ +# threads created here are not explicitly joined but they are part of a ref-count mechanism that +# decrements (with a possible signal of a shutdown callback based on state and count) on thread +# exit function. For now, there is no reasonable way to integrate thread join into the host resolver +# logic, and so this is a false positive. +thread:create_and_init_host_entry diff --git a/bin/elasticurl/main.c b/bin/elasticurl/main.c index a6dfad8ac..4297a4e2f 100644 --- a/bin/elasticurl/main.c +++ b/bin/elasticurl/main.c @@ -64,7 +64,6 @@ struct elasticurl_ctx { enum aws_log_level log_level; enum aws_http_version required_http_version; bool exchange_completed; - bool bootstrap_shutdown_completed; }; static void s_usage(int exit_code) { @@ -539,20 +538,6 @@ static bool s_completion_predicate(void *arg) { return app_ctx->exchange_completed; } -static void s_bootstrap_on_shutdown(void *user_data) { - struct elasticurl_ctx *app_ctx = user_data; - - aws_mutex_lock(&app_ctx->mutex); - app_ctx->bootstrap_shutdown_completed = true; - aws_mutex_unlock(&app_ctx->mutex); - aws_condition_variable_notify_all(&app_ctx->c_var); -} - -static bool s_bootstrap_shutdown_predicate(void *arg) { - struct elasticurl_ctx *app_ctx = arg; - return app_ctx->bootstrap_shutdown_completed; -} - int main(int argc, char **argv) { struct aws_allocator *allocator = aws_default_allocator(); @@ -690,17 +675,12 @@ int main(int argc, char **argv) { } } - struct aws_event_loop_group el_group; - aws_event_loop_group_default_init(&el_group, allocator, 1); - - struct aws_host_resolver resolver; - aws_host_resolver_init_default(&resolver, allocator, 8, &el_group); + struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); + struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, 8, el_group, NULL); struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = &el_group, - .host_resolver = &resolver, - .on_shutdown_complete = s_bootstrap_on_shutdown, - .user_data = &app_ctx, + .event_loop_group = el_group, + .host_resolver = resolver, }; struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); @@ -731,16 +711,17 @@ int main(int argc, char **argv) { aws_mutex_unlock(&app_ctx.mutex); aws_client_bootstrap_release(bootstrap); - aws_mutex_lock(&app_ctx.mutex); - aws_condition_variable_wait_pred(&app_ctx.c_var, &app_ctx.mutex, s_bootstrap_shutdown_predicate, &app_ctx); - aws_mutex_unlock(&app_ctx.mutex); + aws_host_resolver_release(resolver); + aws_event_loop_group_release(el_group); - aws_host_resolver_clean_up(&resolver); - aws_event_loop_group_clean_up(&el_group); + if (aws_global_thread_creator_shutdown_wait_for(5)) { + fprintf(stderr, "Timeout waiting for thread shutdown!"); + exit(1); + } if (tls_ctx) { aws_tls_connection_options_clean_up(&tls_connection_options); - aws_tls_ctx_destroy(tls_ctx); + aws_tls_ctx_release(tls_ctx); aws_tls_ctx_options_clean_up(&tls_ctx_options); } diff --git a/source/connection.c b/source/connection.c index 82757e1bc..e0c215f90 100644 --- a/source/connection.c +++ b/source/connection.c @@ -506,6 +506,9 @@ static void s_http_server_clean_up(struct aws_http_server *server) { if (!server) { return; } + + aws_server_bootstrap_release(server->bootstrap); + /* invoke the user callback */ if (server->on_destroy_complete) { server->on_destroy_complete(server->user_data); @@ -578,7 +581,7 @@ struct aws_http_server *aws_http_server_new(const struct aws_http_server_options } server->alloc = options->allocator; - server->bootstrap = options->bootstrap; + server->bootstrap = aws_server_bootstrap_acquire(options->bootstrap); server->is_using_tls = options->tls_options != NULL; server->initial_window_size = options->initial_window_size; server->user_data = options->server_user_data; diff --git a/source/connection_manager.c b/source/connection_manager.c index 8bef2e015..3d90849bf 100644 --- a/source/connection_manager.c +++ b/source/connection_manager.c @@ -648,6 +648,8 @@ static void s_aws_http_connection_manager_finish_destroy(struct aws_http_connect aws_mutex_clean_up(&manager->lock); + aws_client_bootstrap_release(manager->bootstrap); + if (manager->shutdown_complete_callback) { manager->shutdown_complete_callback(manager->shutdown_complete_user_data); } @@ -815,7 +817,7 @@ struct aws_http_connection_manager *aws_http_connection_manager_new( manager->port = options->port; manager->max_connections = options->max_connections; manager->socket_options = *options->socket_options; - manager->bootstrap = options->bootstrap; + manager->bootstrap = aws_client_bootstrap_acquire(options->bootstrap); manager->system_vtable = g_aws_http_connection_manager_default_system_vtable_ptr; manager->external_ref_count = 1; manager->shutdown_complete_callback = options->shutdown_complete_callback; diff --git a/tests/proxy_test_helper.c b/tests/proxy_test_helper.c index 09370672d..5dd51f20e 100644 --- a/tests/proxy_test_helper.c +++ b/tests/proxy_test_helper.c @@ -62,16 +62,6 @@ void proxy_tester_on_client_connection_shutdown( aws_condition_variable_notify_one(&tester->wait_cvar); } -void proxy_tester_on_client_bootstrap_shutdown(void *user_data) { - struct proxy_tester *tester = user_data; - AWS_FATAL_ASSERT(aws_mutex_lock(&tester->wait_lock) == AWS_OP_SUCCESS); - - tester->client_bootstrap_is_shutdown = true; - - AWS_FATAL_ASSERT(aws_mutex_unlock(&tester->wait_lock) == AWS_OP_SUCCESS); - aws_condition_variable_notify_one(&tester->wait_cvar); -} - int proxy_tester_wait(struct proxy_tester *tester, bool (*pred)(void *user_data)) { ASSERT_SUCCESS(aws_mutex_lock(&tester->wait_lock)); ASSERT_SUCCESS(aws_condition_variable_wait_pred(&tester->wait_cvar, &tester->wait_lock, pred, tester)); @@ -95,11 +85,6 @@ bool proxy_tester_request_complete_pred_fn(void *user_data) { return tester->request_complete || tester->client_connection_is_shutdown; } -bool proxy_tester_client_bootstrap_shutdown_pred(void *user_data) { - struct proxy_tester *tester = user_data; - return tester->client_bootstrap_is_shutdown; -} - int proxy_tester_init(struct proxy_tester *tester, const struct proxy_tester_options *options) { AWS_ZERO_STRUCT(*tester); @@ -126,8 +111,8 @@ int proxy_tester_init(struct proxy_tester *tester, const struct proxy_tester_opt ASSERT_SUCCESS(aws_mutex_init(&tester->wait_lock)); ASSERT_SUCCESS(aws_condition_variable_init(&tester->wait_cvar)); - ASSERT_SUCCESS(aws_event_loop_group_default_init(&tester->event_loop_group, tester->alloc, 1)); - ASSERT_SUCCESS(aws_host_resolver_init_default(&tester->host_resolver, tester->alloc, 8, &tester->event_loop_group)); + tester->event_loop_group = aws_event_loop_group_new_default(tester->alloc, 1, NULL); + tester->host_resolver = aws_host_resolver_new_default(tester->alloc, 8, tester->event_loop_group, NULL); struct aws_socket_options socket_options = { .type = AWS_SOCKET_STREAM, @@ -137,10 +122,8 @@ int proxy_tester_init(struct proxy_tester *tester, const struct proxy_tester_opt }; struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = &tester->event_loop_group, - .host_resolver = &tester->host_resolver, - .on_shutdown_complete = proxy_tester_on_client_bootstrap_shutdown, - .user_data = tester, + .event_loop_group = tester->event_loop_group, + .host_resolver = tester->host_resolver, }; tester->client_bootstrap = aws_client_bootstrap_new(tester->alloc, &bootstrap_options); ASSERT_NOT_NULL(tester->client_bootstrap); @@ -206,14 +189,14 @@ int proxy_tester_clean_up(struct proxy_tester *tester) { } aws_client_bootstrap_release(tester->client_bootstrap); - ASSERT_SUCCESS(proxy_tester_wait(tester, proxy_tester_client_bootstrap_shutdown_pred)); - aws_host_resolver_clean_up(&tester->host_resolver); - aws_event_loop_group_clean_up(&tester->event_loop_group); + aws_host_resolver_release(tester->host_resolver); + aws_event_loop_group_release(tester->event_loop_group); + ASSERT_SUCCESS(aws_global_thread_creator_shutdown_wait_for(10)); if (tester->tls_ctx) { aws_tls_connection_options_clean_up(&tester->tls_connection_options); - aws_tls_ctx_destroy(tester->tls_ctx); + aws_tls_ctx_release(tester->tls_ctx); aws_tls_ctx_options_clean_up(&tester->tls_ctx_options); } diff --git a/tests/proxy_test_helper.h b/tests/proxy_test_helper.h index 61598f4aa..6daaaf95f 100644 --- a/tests/proxy_test_helper.h +++ b/tests/proxy_test_helper.h @@ -43,8 +43,8 @@ struct proxy_tester_options { struct proxy_tester { struct aws_allocator *alloc; struct aws_logger logger; - struct aws_event_loop_group event_loop_group; - struct aws_host_resolver host_resolver; + struct aws_event_loop_group *event_loop_group; + struct aws_host_resolver *host_resolver; struct aws_client_bootstrap *client_bootstrap; struct aws_tls_ctx *tls_ctx; @@ -63,7 +63,6 @@ struct proxy_tester { struct testing_channel *testing_channel; bool client_connection_is_shutdown; - bool client_bootstrap_is_shutdown; /* If we need to wait for some async process*/ struct aws_mutex wait_lock; diff --git a/tests/test_connection.c b/tests/test_connection.c index fd4868575..12e829372 100644 --- a/tests/test_connection.c +++ b/tests/test_connection.c @@ -43,8 +43,8 @@ struct tester_options { struct tester { struct aws_allocator *alloc; struct aws_logger logger; - struct aws_event_loop_group event_loop_group; - struct aws_host_resolver host_resolver; + struct aws_event_loop_group *event_loop_group; + struct aws_host_resolver *host_resolver; struct aws_server_bootstrap *server_bootstrap; struct aws_http_server *server; struct aws_client_bootstrap *client_bootstrap; @@ -64,7 +64,6 @@ struct tester { int server_connection_is_shutdown; int wait_client_connection_is_shutdown; int wait_server_connection_is_shutdown; - bool client_bootstrap_is_shutdown; bool server_is_shutdown; struct aws_http_connection *new_client_connection; @@ -177,15 +176,6 @@ static void s_tester_on_client_connection_shutdown( AWS_FATAL_ASSERT(aws_mutex_unlock(&tester->wait_lock) == AWS_OP_SUCCESS); aws_condition_variable_notify_one(&tester->wait_cvar); } -static void s_tester_on_client_bootstrap_shutdown(void *user_data) { - struct tester *tester = user_data; - AWS_FATAL_ASSERT(aws_mutex_lock(&tester->wait_lock) == AWS_OP_SUCCESS); - - tester->client_bootstrap_is_shutdown = true; - - AWS_FATAL_ASSERT(aws_mutex_unlock(&tester->wait_lock) == AWS_OP_SUCCESS); - aws_condition_variable_notify_one(&tester->wait_cvar); -} static int s_tester_wait(struct tester *tester, bool (*pred)(void *user_data)) { int local_wait_result; @@ -230,11 +220,6 @@ static bool s_tester_server_shutdown_pred(void *user_data) { return tester->server_is_shutdown; } -static bool s_tester_client_bootstrap_shutdown_pred(void *user_data) { - struct tester *tester = user_data; - return tester->client_bootstrap_is_shutdown; -} - static int s_tester_init(struct tester *tester, const struct tester_options *options) { AWS_ZERO_STRUCT(*tester); @@ -253,9 +238,9 @@ static int s_tester_init(struct tester *tester, const struct tester_options *opt ASSERT_SUCCESS(aws_mutex_init(&tester->wait_lock)); ASSERT_SUCCESS(aws_condition_variable_init(&tester->wait_cvar)); - ASSERT_SUCCESS(aws_event_loop_group_default_init(&tester->event_loop_group, tester->alloc, 1)); - ASSERT_SUCCESS(aws_host_resolver_init_default(&tester->host_resolver, tester->alloc, 8, &tester->event_loop_group)); - tester->server_bootstrap = aws_server_bootstrap_new(tester->alloc, &tester->event_loop_group); + tester->event_loop_group = aws_event_loop_group_new_default(tester->alloc, 1, NULL); + tester->host_resolver = aws_host_resolver_new_default(tester->alloc, 8, tester->event_loop_group, NULL); + tester->server_bootstrap = aws_server_bootstrap_new(tester->alloc, tester->event_loop_group); ASSERT_NOT_NULL(tester->server_bootstrap); struct aws_socket_options socket_options = { @@ -295,10 +280,8 @@ static int s_tester_init(struct tester *tester, const struct tester_options *opt } struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = &tester->event_loop_group, - .host_resolver = &tester->host_resolver, - .on_shutdown_complete = s_tester_on_client_bootstrap_shutdown, - .user_data = tester, + .event_loop_group = tester->event_loop_group, + .host_resolver = tester->host_resolver, }; tester->client_bootstrap = aws_client_bootstrap_new(tester->alloc, &bootstrap_options); ASSERT_NOT_NULL(tester->client_bootstrap); @@ -335,8 +318,11 @@ static int s_tester_clean_up(struct tester *tester) { ASSERT_SUCCESS(s_tester_wait(tester, s_tester_server_shutdown_pred)); } aws_server_bootstrap_release(tester->server_bootstrap); - aws_host_resolver_clean_up(&tester->host_resolver); - aws_event_loop_group_clean_up(&tester->event_loop_group); + aws_client_bootstrap_release(tester->client_bootstrap); + aws_host_resolver_release(tester->host_resolver); + aws_event_loop_group_release(tester->event_loop_group); + ASSERT_SUCCESS(aws_global_thread_creator_shutdown_wait_for(10)); + aws_http_library_clean_up(); aws_logger_clean_up(&tester->logger); aws_mutex_clean_up(&tester->wait_lock); @@ -386,9 +372,6 @@ static int s_test_connection_setup_shutdown(struct aws_allocator *allocator, voi release_all_server_connections(&tester); ASSERT_SUCCESS(s_tester_wait(&tester, s_tester_connection_shutdown_pred)); - aws_client_bootstrap_release(tester.client_bootstrap); - ASSERT_SUCCESS(s_tester_wait(&tester, s_tester_client_bootstrap_shutdown_pred)); - ASSERT_SUCCESS(s_tester_clean_up(&tester)); return AWS_OP_SUCCESS; } @@ -413,8 +396,6 @@ static int s_test_connection_destroy_server_with_connection_existing(struct aws_ /* release memory */ release_all_client_connections(&tester); release_all_server_connections(&tester); - aws_client_bootstrap_release(tester.client_bootstrap); - ASSERT_SUCCESS(s_tester_wait(&tester, s_tester_client_bootstrap_shutdown_pred)); ASSERT_SUCCESS(s_tester_clean_up(&tester)); return AWS_OP_SUCCESS; @@ -458,9 +439,6 @@ static int s_test_connection_destroy_server_with_multiple_connections_existing( release_all_client_connections(&tester); release_all_server_connections(&tester); - aws_client_bootstrap_release(tester.client_bootstrap); - ASSERT_SUCCESS(s_tester_wait(&tester, s_tester_client_bootstrap_shutdown_pred)); - ASSERT_SUCCESS(s_tester_clean_up(&tester)); return AWS_OP_SUCCESS; } @@ -540,25 +518,24 @@ static int s_test_connection_server_shutting_down_new_connection_setup_fail( }; /* create a new eventloop for the new connection and block the new connection. Waiting server to begin shutting * down. */ - struct aws_event_loop_group event_loop_group; - ASSERT_SUCCESS(aws_event_loop_group_default_init(&event_loop_group, allocator, 1)); + struct aws_event_loop_group *event_loop_group = aws_event_loop_group_new_default(allocator, 1, NULL); /* get the first eventloop, which will be the eventloop for client to connect */ - struct aws_event_loop *current_eventloop = aws_event_loop_group_get_loop_at(&event_loop_group, 0); + struct aws_event_loop *current_eventloop = aws_event_loop_group_get_loop_at(event_loop_group, 0); struct aws_task *block_task = aws_mem_acquire(allocator, sizeof(struct aws_task)); aws_task_init(block_task, s_block_task, &tester, "wait_a_bit"); aws_event_loop_schedule_task_now(current_eventloop, block_task); /* get the first eventloop of tester, which will be the eventloop for server listener socket, block the listener * socket */ - struct aws_event_loop *server_eventloop = aws_event_loop_group_get_loop_at(&tester.event_loop_group, 0); + struct aws_event_loop *server_eventloop = aws_event_loop_group_get_loop_at(tester.event_loop_group, 0); struct aws_task *server_block_task = aws_mem_acquire(allocator, sizeof(struct aws_task)); aws_task_init(server_block_task, s_block_task, &tester, "wait_a_bit"); aws_event_loop_schedule_task_now(server_eventloop, server_block_task); struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = &event_loop_group, - .host_resolver = &tester.host_resolver, + .event_loop_group = event_loop_group, + .host_resolver = tester.host_resolver, }; struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); struct aws_http_client_connection_options client_options = AWS_HTTP_CLIENT_CONNECTION_OPTIONS_INIT; @@ -603,9 +580,7 @@ static int s_test_connection_server_shutting_down_new_connection_setup_fail( release_all_client_connections(&tester); release_all_server_connections(&tester); aws_client_bootstrap_release(bootstrap); - aws_client_bootstrap_release(tester.client_bootstrap); - ASSERT_SUCCESS(s_tester_wait(&tester, s_tester_client_bootstrap_shutdown_pred)); - aws_event_loop_group_clean_up(&event_loop_group); + aws_event_loop_group_release(event_loop_group); ASSERT_SUCCESS(s_tester_clean_up(&tester)); return AWS_OP_SUCCESS; diff --git a/tests/test_connection_manager.c b/tests/test_connection_manager.c index 43fe08179..361acf23d 100644 --- a/tests/test_connection_manager.c +++ b/tests/test_connection_manager.c @@ -39,8 +39,8 @@ struct cm_tester_options { struct cm_tester { struct aws_allocator *allocator; - struct aws_event_loop_group event_loop_group; - struct aws_host_resolver host_resolver; + struct aws_event_loop_group *event_loop_group; + struct aws_host_resolver *host_resolver; struct aws_client_bootstrap *client_bootstrap; @@ -60,7 +60,6 @@ struct cm_tester { size_t wait_for_connection_count; bool is_shutdown_complete; - bool is_client_bootstrap_shutdown_complete; struct aws_http_connection_manager_system_vtable *mock_table; @@ -98,17 +97,6 @@ static void s_cm_tester_on_cm_shutdown_complete(void *user_data) { aws_condition_variable_notify_one(&tester->signal); } -static void s_cm_tester_on_client_bootstrap_shutdown_complete(void *user_data) { - struct cm_tester *tester = user_data; - AWS_FATAL_ASSERT(tester == &s_tester); - aws_mutex_lock(&tester->lock); - - tester->is_client_bootstrap_shutdown_complete = true; - - aws_mutex_unlock(&tester->lock); - aws_condition_variable_notify_one(&tester->signal); -} - static struct aws_event_loop *s_new_event_loop( struct aws_allocator *alloc, aws_io_clock_fn *clock, @@ -140,16 +128,12 @@ static int s_cm_tester_init(struct cm_tester_options *options) { if (options->mock_table) { clock_fn = options->mock_table->get_monotonic_time; } - ASSERT_SUCCESS( - aws_event_loop_group_init(&tester->event_loop_group, tester->allocator, clock_fn, 1, s_new_event_loop, NULL)); - ASSERT_SUCCESS( - aws_host_resolver_init_default(&tester->host_resolver, tester->allocator, 8, &tester->event_loop_group)); + tester->event_loop_group = aws_event_loop_group_new(tester->allocator, clock_fn, 1, s_new_event_loop, NULL, NULL); + tester->host_resolver = aws_host_resolver_new_default(tester->allocator, 8, tester->event_loop_group, NULL); struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = &tester->event_loop_group, - .host_resolver = &tester->host_resolver, - .on_shutdown_complete = s_cm_tester_on_client_bootstrap_shutdown_complete, - .user_data = tester, + .event_loop_group = tester->event_loop_group, + .host_resolver = tester->host_resolver, }; tester->client_bootstrap = aws_client_bootstrap_new(tester->allocator, &bootstrap_options); ASSERT_NOT_NULL(tester->client_bootstrap); @@ -355,26 +339,6 @@ static int s_wait_on_shutdown_complete(void) { return signal_error; } -static bool s_is_client_bootstrap_shutdown_complete(void *context) { - (void)context; - - struct cm_tester *tester = &s_tester; - - return tester->is_client_bootstrap_shutdown_complete; -} - -static int s_wait_on_client_bootstrap_shutdown_complete(void) { - struct cm_tester *tester = &s_tester; - - ASSERT_SUCCESS(aws_mutex_lock(&tester->lock)); - - int signal_error = aws_condition_variable_wait_pred( - &tester->signal, &tester->lock, s_is_client_bootstrap_shutdown_complete, tester); - - ASSERT_SUCCESS(aws_mutex_unlock(&tester->lock)); - return signal_error; -} - static int s_cm_tester_clean_up(void) { struct cm_tester *tester = &s_tester; @@ -398,14 +362,14 @@ static int s_cm_tester_clean_up(void) { s_wait_on_shutdown_complete(); aws_client_bootstrap_release(tester->client_bootstrap); - ASSERT_SUCCESS(s_wait_on_client_bootstrap_shutdown_complete()); - aws_host_resolver_clean_up(&tester->host_resolver); - aws_event_loop_group_clean_up(&tester->event_loop_group); + aws_host_resolver_release(tester->host_resolver); + aws_event_loop_group_release(tester->event_loop_group); + ASSERT_SUCCESS(aws_global_thread_creator_shutdown_wait_for(10)); aws_tls_ctx_options_clean_up(&tester->tls_ctx_options); aws_tls_connection_options_clean_up(&tester->tls_connection_options); - aws_tls_ctx_destroy(tester->tls_ctx); + aws_tls_ctx_release(tester->tls_ctx); aws_mutex_clean_up(&tester->lock); aws_condition_variable_clean_up(&tester->signal); diff --git a/tests/test_tls.c b/tests/test_tls.c index 1520a0180..799f498be 100644 --- a/tests/test_tls.c +++ b/tests/test_tls.c @@ -21,9 +21,8 @@ /* Singleton used by tests in this file */ struct test_ctx { struct aws_allocator *alloc; - struct aws_logger logger; - struct aws_event_loop_group event_loop_group; - struct aws_host_resolver host_resolver; + struct aws_event_loop_group *event_loop_group; + struct aws_host_resolver *host_resolver; struct aws_tls_ctx *tls_ctx; struct aws_client_bootstrap *client_bootstrap; struct aws_http_connection *client_connection; @@ -84,15 +83,23 @@ static bool s_test_connection_shutdown_pred(void *user_data) { static int s_on_stream_body(struct aws_http_stream *stream, const struct aws_byte_cursor *data, void *user_data) { (void)stream; struct test_ctx *test = user_data; + + AWS_FATAL_ASSERT(aws_mutex_lock(&test->wait_lock) == AWS_OP_SUCCESS); test->body_size += data->len; + AWS_FATAL_ASSERT(aws_mutex_unlock(&test->wait_lock) == AWS_OP_SUCCESS); + return AWS_OP_SUCCESS; } static void s_on_stream_complete(struct aws_http_stream *stream, int error_code, void *user_data) { (void)stream; struct test_ctx *test = user_data; + + AWS_FATAL_ASSERT(aws_mutex_lock(&test->wait_lock) == AWS_OP_SUCCESS); test->wait_result = error_code; test->stream_complete = true; + AWS_FATAL_ASSERT(aws_mutex_unlock(&test->wait_lock) == AWS_OP_SUCCESS); + aws_condition_variable_notify_one(&test->wait_cvar); } @@ -121,19 +128,15 @@ static int s_test_tls_download_medium_file_general( AWS_ZERO_STRUCT(test); test.alloc = allocator; - struct aws_logger_standard_options logger_options = {.file = stdout, .level = AWS_LL_DEBUG}; - aws_logger_init_standard(&test.logger, allocator, &logger_options); - aws_logger_set(&test.logger); - aws_mutex_init(&test.wait_lock); aws_condition_variable_init(&test.wait_cvar); - ASSERT_SUCCESS(aws_event_loop_group_default_init(&test.event_loop_group, test.alloc, 1)); - ASSERT_SUCCESS(aws_host_resolver_init_default(&test.host_resolver, test.alloc, 1, &test.event_loop_group)); + test.event_loop_group = aws_event_loop_group_new_default(test.alloc, 1, NULL); + test.host_resolver = aws_host_resolver_new_default(test.alloc, 1, test.event_loop_group, NULL); struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = &test.event_loop_group, - .host_resolver = &test.host_resolver, + .event_loop_group = test.event_loop_group, + .host_resolver = test.host_resolver, }; ASSERT_NOT_NULL(test.client_bootstrap = aws_client_bootstrap_new(test.alloc, &bootstrap_options)); struct aws_tls_ctx_options tls_ctx_options; @@ -201,15 +204,14 @@ static int s_test_tls_download_medium_file_general( ASSERT_SUCCESS(s_test_wait(&test, s_test_connection_shutdown_pred)); aws_client_bootstrap_release(test.client_bootstrap); - aws_host_resolver_clean_up(&test.host_resolver); - aws_event_loop_group_clean_up(&test.event_loop_group); + aws_host_resolver_release(test.host_resolver); + aws_event_loop_group_release(test.event_loop_group); + + ASSERT_SUCCESS(aws_global_thread_creator_shutdown_wait_for(10)); aws_tls_ctx_options_clean_up(&tls_ctx_options); aws_tls_connection_options_clean_up(&tls_connection_options); - aws_tls_ctx_destroy(test.tls_ctx); - - aws_logger_set(NULL); - aws_logger_clean_up(&test.logger); + aws_tls_ctx_release(test.tls_ctx); aws_mutex_clean_up(&test.wait_lock); aws_condition_variable_clean_up(&test.wait_cvar);