diff --git a/src/ssb.c b/src/ssb.c index af699946f..001acec2a 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -204,7 +204,6 @@ typedef struct _tf_ssb_t uv_timer_t broadcast_cleanup_timer; uv_timer_t broadcast_timer; uv_timer_t trace_timer; - uv_timer_t settings_timer; uv_tcp_t server; uint8_t pub[crypto_sign_PUBLICKEYBYTES]; @@ -357,7 +356,7 @@ static void _tf_ssb_nonce_inc(uint8_t* nonce); static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size); static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value); static void _tf_ssb_update_settings(tf_ssb_t* ssb); -static void _tf_ssb_start_update_settings(tf_ssb_t* ssb, int delay_ms); +static void _tf_ssb_start_update_settings(tf_ssb_t* ssb); static void _tf_ssb_add_debug_close(tf_ssb_t* ssb, tf_ssb_connection_t* connection, const char* reason) { @@ -2219,7 +2218,7 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path _tf_ssb_update_settings(ssb); tf_ssb_rpc_register(ssb); - _tf_ssb_start_update_settings(ssb, 5000); + _tf_ssb_start_update_settings(ssb); return ssb; } @@ -2368,6 +2367,7 @@ static void _tf_ssb_on_timer_close(uv_handle_t* handle) void tf_ssb_destroy(tf_ssb_t* ssb) { + tf_printf("tf_ssb_destroy\n"); tf_ssb_connections_destroy(ssb->connections_tracker); ssb->connections_tracker = NULL; @@ -2401,11 +2401,6 @@ void tf_ssb_destroy(tf_ssb_t* ssb) uv_close((uv_handle_t*)&ssb->server, _tf_ssb_on_handle_close); } - if (ssb->settings_timer.data && !uv_is_closing((uv_handle_t*)&ssb->settings_timer)) - { - uv_close((uv_handle_t*)&ssb->settings_timer, _tf_ssb_on_handle_close); - } - for (int i = 0; i < ssb->timers_count; i++) { uv_close((uv_handle_t*)&ssb->timers[i]->timer, _tf_ssb_on_timer_close); @@ -2414,18 +2409,21 @@ void tf_ssb_destroy(tf_ssb_t* ssb) tf_free(ssb->timers); ssb->timers = NULL; + tf_printf("Waiting for closes.\n"); + while (ssb->broadcast_listener.data || ssb->broadcast_sender.data || ssb->broadcast_timer.data || ssb->broadcast_cleanup_timer.data || ssb->trace_timer.data || - ssb->settings_timer.data || ssb->server.data || ssb->ref_count) { uv_run(ssb->loop, UV_RUN_ONCE); } + tf_printf("Waiting for rpc.\n"); + while (ssb->rpc) { tf_ssb_rpc_callback_node_t* node = ssb->rpc; @@ -2482,6 +2480,25 @@ void tf_ssb_destroy(tf_ssb_t* ssb) } tf_free(node); } + + tf_printf("rpc=%p conn_changed=%p mess_add=%p blob_want_add=%p broadcast_change=%p\n", + ssb->rpc, + ssb->connections_changed, + ssb->message_added, + ssb->blob_want_added, + ssb->broadcasts_changed); + + tf_printf("Closing connections.\n"); + tf_ssb_connection_t* connection = ssb->connections; + while (connection) + { + tf_ssb_connection_t* next = connection->next; + tf_printf("close %p\n", connection); + tf_ssb_connection_close(connection); + connection = next; + } + tf_printf("Closed.\n"); + if (ssb->loop == &ssb->own_loop) { int r = uv_loop_close(ssb->loop); @@ -2490,6 +2507,7 @@ void tf_ssb_destroy(tf_ssb_t* ssb) tf_printf("uv_loop_close: %s\n", uv_strerror(r)); } } + tf_printf("loop closed\n"); if (ssb->own_context) { JS_FreeContext(ssb->context); @@ -2515,8 +2533,10 @@ void tf_ssb_destroy(tf_ssb_t* ssb) sqlite3_close(ssb->db_readers[i]); } tf_free(ssb->db_readers); + tf_printf("destroying mutexes\n"); uv_mutex_destroy(&ssb->db_readers_lock); uv_mutex_destroy(&ssb->db_writer_lock); + tf_printf("mutexes destroyed\n"); tf_free((void*)ssb->db_path); tf_free(ssb->room_name); ssb->room_name = NULL; @@ -3893,12 +3913,14 @@ static void _tf_ssb_update_settings_work(uv_work_t* work) static void _tf_ssb_update_settings_after_work(uv_work_t* work, int result) { update_settings_t* update = work->data; + tf_ssb_unref(update->ssb); tf_ssb_set_is_room(update->ssb, update->is_room); tf_ssb_set_room_name(update->ssb, update->room_name); + _tf_ssb_start_update_settings(update->ssb); tf_free(update); } -static void _tf_ssb_start_update_settings_timer(uv_timer_t* timer) +static void _tf_ssb_start_update_settings_timer(tf_ssb_t* ssb, void* user_data) { update_settings_t* update = tf_malloc(sizeof(update_settings_t)); *update = (update_settings_t) @@ -3907,9 +3929,10 @@ static void _tf_ssb_start_update_settings_timer(uv_timer_t* timer) { .data = update, }, - .ssb = timer->data, + .ssb = ssb, }; - int result = uv_queue_work(tf_ssb_get_loop(timer->data), &update->work, _tf_ssb_update_settings_work, _tf_ssb_update_settings_after_work); + tf_ssb_ref(ssb); + int result = uv_queue_work(tf_ssb_get_loop(ssb), &update->work, _tf_ssb_update_settings_work, _tf_ssb_update_settings_after_work); if (result) { _tf_ssb_update_settings_after_work(&update->work, result); @@ -3927,16 +3950,14 @@ static void _tf_ssb_update_settings(tf_ssb_t* ssb) }, .ssb = ssb, }; + tf_ssb_ref(ssb); _tf_ssb_update_settings_work(&update->work); _tf_ssb_update_settings_after_work(&update->work, 0); } -static void _tf_ssb_start_update_settings(tf_ssb_t* ssb, int delay_ms) +static void _tf_ssb_start_update_settings(tf_ssb_t* ssb) { - ssb->settings_timer.data = ssb; - uv_timer_init(ssb->loop, &ssb->settings_timer); - uv_timer_start(&ssb->settings_timer, _tf_ssb_start_update_settings_timer, delay_ms, delay_ms); - uv_unref((uv_handle_t*)&ssb->settings_timer); + tf_ssb_schedule_work(ssb, 5000, _tf_ssb_start_update_settings_timer, NULL); } void tf_ssb_set_verbose(tf_ssb_t* ssb, bool verbose) @@ -3976,4 +3997,5 @@ void tf_ssb_schedule_work(tf_ssb_t* ssb, int delay_ms, void (*callback)(tf_ssb_t ssb->timers[ssb->timers_count++] = timer; uv_timer_init(ssb->loop, &timer->timer); uv_timer_start(&timer->timer, _tf_ssb_scheduled_timer, delay_ms, 0); + uv_unref((uv_handle_t*)&timer->timer); } diff --git a/src/ssb.rpc.c b/src/ssb.rpc.c index 4267c2e9d..89e41690d 100644 --- a/src/ssb.rpc.c +++ b/src/ssb.rpc.c @@ -1333,6 +1333,7 @@ static void _tf_ssb_rpc_delete_blobs_work(uv_work_t* work) static void _tf_ssb_rpc_delete_blobs_after_work(uv_work_t* work, int status) { delete_blobs_work_t* delete = work->data; + tf_ssb_unref(delete->ssb); tf_free(delete); } @@ -1340,11 +1341,13 @@ static void _tf_ssb_rpc_start_delete_callback(tf_ssb_t* ssb, void* user_data) { delete_blobs_work_t* work = tf_malloc(sizeof(delete_blobs_work_t)); *work = (delete_blobs_work_t) { .work = { .data = work}, .ssb = ssb }; + tf_ssb_ref(ssb); int r = uv_queue_work(tf_ssb_get_loop(ssb), &work->work, _tf_ssb_rpc_delete_blobs_work, _tf_ssb_rpc_delete_blobs_after_work); if (r) { tf_printf("uv_queue_work: %s\n", uv_strerror(r)); tf_free(work); + tf_ssb_unref(ssb); } } diff --git a/src/ssb.tests.c b/src/ssb.tests.c index becc1d57b..7fdbeaaa4 100644 --- a/src/ssb.tests.c +++ b/src/ssb.tests.c @@ -301,11 +301,16 @@ void tf_ssb_test_ssb(const tf_test_options_t* options) uv_close((uv_handle_t*)&idle0, NULL); uv_close((uv_handle_t*)&idle1, NULL); + tf_printf("final run\n"); uv_run(&loop, UV_RUN_DEFAULT); + tf_printf("done\n"); + tf_printf("destroy 0\n"); tf_ssb_destroy(ssb0); + tf_printf("destroy 1\n"); tf_ssb_destroy(ssb1); + tf_printf("close\n"); uv_loop_close(&loop); }