diff --git a/src/http.c b/src/http.c index bae70a62..7deff0c3 100644 --- a/src/http.c +++ b/src/http.c @@ -442,7 +442,7 @@ static size_t _http_on_read_plain_internal(tf_http_connection_t* connection, con if (connection->content_length) { - connection->body = tf_malloc(connection->content_length); + connection->body = tf_realloc(connection->body, connection->content_length); } if (!_http_find_handler(connection->http, connection->path, &connection->callback, &connection->trace_name, &connection->user_data) || @@ -940,9 +940,16 @@ void tf_http_request_ref(tf_http_request_t* request) void tf_http_request_unref(tf_http_request_t* request) { + bool connection_destroyed = false; + if (--request->connection->ref_count == 0) { - if (!request->connection->is_websocket) + if (request->connection->http->is_shutting_down) + { + _http_connection_destroy(request->connection, "unref during shutdown"); + connection_destroyed = true; + } + else if (!request->connection->is_websocket) { _http_reset_connection(request->connection); } @@ -950,7 +957,10 @@ void tf_http_request_unref(tf_http_request_t* request) if (--request->ref_count == 0) { - request->connection->request = NULL; + if (!connection_destroyed) + { + request->connection->request = NULL; + } tf_free(request); } } diff --git a/src/ssb.c b/src/ssb.c index 343c5f8a..af52899e 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -2462,6 +2462,7 @@ void tf_ssb_destroy(tf_ssb_t* ssb) tf_printf("uv loop closed.\n"); if (ssb->own_context) { + tf_printf("closing ssb context\n"); JS_FreeContext(ssb->context); JS_FreeRuntime(ssb->runtime); ssb->own_context = false; diff --git a/src/task.c b/src/task.c index 98a7cdbd..4aeb4600 100644 --- a/src/task.c +++ b/src/task.c @@ -1911,10 +1911,10 @@ void tf_task_destroy(tf_task_t* task) uv_run(&task->_loop, UV_RUN_ONCE); } - int index = 0; + //int index = 0; while (uv_loop_close(&task->_loop) != 0) { - if (index++ > 0) + //if (index++ > 0) { tf_printf("--\n"); uv_print_all_handles(&task->_loop, stdout); diff --git a/src/tests.c b/src/tests.c index ded78722..ea5f54ab 100644 --- a/src/tests.c +++ b/src/tests.c @@ -737,6 +737,71 @@ static void _test_http(const tf_test_options_t* options) uv_thread_join(&thread); } +static void _test_auto_process_exit(uv_process_t* process, int64_t status, int termination_signal) +{ + tf_printf("Process exit %d signal=%d.\n", (int)WEXITSTATUS(status), termination_signal); + assert(WEXITSTATUS(status) == 0); + process->data = NULL; + uv_close((uv_handle_t*)process, NULL); +} + +static void _test_auto(const tf_test_options_t* options) +{ + uv_loop_t loop = { 0 }; + uv_loop_init(&loop); + + char executable[1024]; + size_t size = sizeof(executable); + uv_exepath(executable, &size); + + unlink("out/selenium.sqlite"); + unlink("out/selenium.sqlite-shm"); + unlink("out/selenium.sqlite-wal"); + + char* args[] = { executable, "run", "-d", "out/selenium.sqlite", "-b", "0", "-p", "8888", NULL }; + + uv_stdio_container_t io[3] = + { + { .flags = UV_INHERIT_FD }, + { .flags = UV_INHERIT_FD }, + { .flags = UV_INHERIT_FD }, + }; + + uv_process_options_t process_options = {0}; + process_options.args = args; + process_options.exit_cb = _test_auto_process_exit; + process_options.stdio = io; + process_options.stdio_count = sizeof(io) / sizeof(*io); + process_options.file = args[0]; + + uv_process_t process = { .data = &process }; + int spawn_result = uv_spawn(&loop, &process, &process_options); + if (spawn_result) + { + abort(); + } + + char* selenium_args[] = { "python3", "tools/autotest.py", NULL }; + process_options.args = selenium_args; + process_options.exit_cb = _test_auto_process_exit; + process_options.file = selenium_args[0]; + + uv_process_t selenium = { .data = &selenium }; + spawn_result = uv_spawn(&loop, &selenium, &process_options); + if (spawn_result) + { + abort(); + } + + while (selenium.data) + { + uv_run(&loop, UV_RUN_ONCE); + } + uv_process_kill(&process, SIGTERM); + uv_run(&loop, UV_RUN_DEFAULT); + uv_loop_close(&loop); +} + static void _tf_test_run(const tf_test_options_t* options, const char* name, void (*test)(const tf_test_options_t* options), bool opt_in) { bool specified = false; @@ -800,6 +865,7 @@ void tf_tests(const tf_test_options_t* options) _tf_test_run(options, "b64", _test_b64, false); _tf_test_run(options, "rooms", tf_ssb_test_rooms, false); _tf_test_run(options, "bench", tf_ssb_test_bench, false); + _tf_test_run(options, "auto", _test_auto, false); _tf_test_run(options, "go-ssb-room", tf_ssb_test_go_ssb_room, true); tf_printf("Tests completed.\n"); #endif diff --git a/tools/autotest.py b/tools/autotest.py index f61559f7..b6036f48 100755 --- a/tools/autotest.py +++ b/tools/autotest.py @@ -10,13 +10,6 @@ import subprocess import sys import time -for path in ('out/selenium.sqlite', 'out/selenium.sqlite-shm', 'out/selenium.sqlite-wal'): - try: - os.unlink(path) - except: - pass -tf = subprocess.Popen(['out/debug/tildefriends', 'run', '-d', 'out/selenium.sqlite', '-b', '0', '-p', '8888'] + sys.argv[1:]) - def exists_in_shadow_root(shadow_root, by, value): return lambda driver: shadow_root.find_element(by, value) @@ -165,8 +158,6 @@ finally: driver.close() driver.quit() -tf.terminate() - if success: print('\033[92mTEST SUCCEEDED.\033[0m') else: