Have we achieved clean shutdown?

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4841 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2024-02-13 23:07:36 +00:00
parent e7791d38ff
commit 685754895b
6 changed files with 84 additions and 75 deletions

View File

@ -702,6 +702,31 @@ void tf_http_destroy(tf_http_t* http)
_http_connection_destroy(http->connections[i], "tf_http_destroy"); _http_connection_destroy(http->connections[i], "tf_http_destroy");
} }
for (int i = 0; i < http->listeners_count; i++)
{
tf_http_listener_t* listener = http->listeners[i];
if (listener->cleanup)
{
listener->cleanup(listener->user_data);
listener->cleanup = NULL;
}
}
for (int i = 0; i < http->handlers_count; i++)
{
if (http->handlers[i].cleanup)
{
http->handlers[i].cleanup(http->handlers[i].user_data);
http->handlers[i].cleanup = NULL;
}
}
if (http->user_data_cleanup)
{
http->user_data_cleanup(http->user_data);
http->user_data = NULL;
}
if (http->connections_count == 0) if (http->connections_count == 0)
{ {
tf_free(http->connections); tf_free(http->connections);
@ -710,10 +735,6 @@ void tf_http_destroy(tf_http_t* http)
for (int i = 0; i < http->listeners_count; i++) for (int i = 0; i < http->listeners_count; i++)
{ {
tf_http_listener_t* listener = http->listeners[i]; tf_http_listener_t* listener = http->listeners[i];
if (listener->cleanup)
{
listener->cleanup(listener->user_data);
}
uv_close((uv_handle_t*)&listener->tcp, _http_free_listener_on_close); uv_close((uv_handle_t*)&listener->tcp, _http_free_listener_on_close);
} }
tf_free(http->listeners); tf_free(http->listeners);
@ -727,20 +748,10 @@ void tf_http_destroy(tf_http_t* http)
tf_free((void*)http->handlers[i].pattern); tf_free((void*)http->handlers[i].pattern);
http->handlers[i].pattern = NULL; http->handlers[i].pattern = NULL;
} }
if (http->handlers[i].cleanup)
{
http->handlers[i].cleanup(http->handlers[i].user_data);
}
} }
tf_free(http->handlers); tf_free(http->handlers);
http->handlers_count = 0; http->handlers_count = 0;
if (http->user_data_cleanup)
{
http->user_data_cleanup(http->user_data);
http->user_data = NULL;
}
tf_free(http); tf_free(http);
} }
} }

View File

@ -2,6 +2,7 @@
#include "file.js.h" #include "file.js.h"
#include "http.h" #include "http.h"
#include "log.h"
#include "mem.h" #include "mem.h"
#include "task.h" #include "task.h"
#include "tlscontext.js.h" #include "tlscontext.js.h"

View File

@ -2376,8 +2376,12 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
{ {
tf_printf("tf_ssb_destroy\n"); tf_printf("tf_ssb_destroy\n");
ssb->shutting_down = true; ssb->shutting_down = true;
if (ssb->connections_tracker)
{
tf_ssb_connections_destroy(ssb->connections_tracker); tf_ssb_connections_destroy(ssb->connections_tracker);
ssb->connections_tracker = NULL; ssb->connections_tracker = NULL;
}
if (ssb->broadcast_listener.data && !uv_is_closing((uv_handle_t*)&ssb->broadcast_listener)) if (ssb->broadcast_listener.data && !uv_is_closing((uv_handle_t*)&ssb->broadcast_listener))
{ {
@ -2489,19 +2493,11 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
tf_free(node); 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_printf("Closing connections.\n");
tf_ssb_connection_t* connection = ssb->connections; tf_ssb_connection_t* connection = ssb->connections;
while (connection) while (connection)
{ {
tf_ssb_connection_t* next = connection->next; tf_ssb_connection_t* next = connection->next;
tf_printf("close %p\n", connection);
tf_ssb_connection_close(connection); tf_ssb_connection_close(connection);
connection = next; connection = next;
} }
@ -2515,13 +2511,18 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
tf_printf("uv_loop_close: %s\n", uv_strerror(r)); tf_printf("uv_loop_close: %s\n", uv_strerror(r));
} }
} }
tf_printf("loop closed\n"); tf_printf("uv loop closed.\n");
if (ssb->own_context) if (ssb->own_context)
{ {
JS_FreeContext(ssb->context); JS_FreeContext(ssb->context);
JS_FreeRuntime(ssb->runtime); JS_FreeRuntime(ssb->runtime);
ssb->own_context = false;
} }
if (ssb->db_writer)
{
sqlite3_close(ssb->db_writer); sqlite3_close(ssb->db_writer);
ssb->db_writer = NULL;
}
while (ssb->broadcasts) while (ssb->broadcasts)
{ {
tf_ssb_broadcast_t* broadcast = ssb->broadcasts; tf_ssb_broadcast_t* broadcast = ssb->broadcasts;
@ -2540,17 +2541,28 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
{ {
sqlite3_close(ssb->db_readers[i]); sqlite3_close(ssb->db_readers[i]);
} }
ssb->db_readers_count = 0;
if (ssb->db_readers)
{
tf_free(ssb->db_readers); tf_free(ssb->db_readers);
tf_printf("destroying mutexes\n"); ssb->db_readers = NULL;
uv_mutex_destroy(&ssb->db_readers_lock); }
uv_mutex_destroy(&ssb->db_writer_lock); if (ssb->db_path)
tf_printf("mutexes destroyed\n"); {
tf_free((void*)ssb->db_path); tf_free((void*)ssb->db_path);
ssb->db_path = NULL;
}
if (ssb->room_name)
{
tf_free(ssb->room_name); tf_free(ssb->room_name);
ssb->room_name = NULL; ssb->room_name = NULL;
}
if (ssb->connection_ref_count == 0) if (ssb->connection_ref_count == 0)
{ {
uv_mutex_destroy(&ssb->db_readers_lock);
uv_mutex_destroy(&ssb->db_writer_lock);
tf_free(ssb); tf_free(ssb);
} }
} }

View File

@ -1418,6 +1418,7 @@ void tf_task_remove_child(tf_task_t* task, tf_taskstub_t* child)
{ {
task_child_node_t* node = *it; task_child_node_t* node = *it;
*it = node->next; *it = node->next;
JS_FreeValue(task->_context, tf_taskstub_get_task_object(child));
tf_free(node); tf_free(node);
task->_child_count--; task->_child_count--;
break; break;
@ -1809,20 +1810,25 @@ static void _tf_task_on_handle_close(uv_handle_t* handle)
handle->data = NULL; handle->data = NULL;
} }
JSValue tf_taskstub_kill(tf_taskstub_t* stub);
void tf_task_destroy(tf_task_t* task) void tf_task_destroy(tf_task_t* task)
{ {
while (task->_children) while (task->_children)
{ {
task_child_node_t* node = task->_children; for (task_child_node_t* node = task->_children; node; node = node->next)
task->_children = node->next; {
tf_taskstub_destroy(node->stub); JS_FreeValue(task->_context, tf_taskstub_kill(node->stub));
tf_free(node);
}
uv_run(&task->_loop, UV_RUN_ONCE);
} }
if (task->_parent) if (task->_parent)
{ {
tf_taskstub_destroy(task->_parent); tf_taskstub_t* parent = task->_parent;
task->_parent = NULL; task->_parent = NULL;
JS_RunGC(task->_runtime); tf_packetstream_close(tf_taskstub_get_stream(parent));
JS_FreeValue(task->_context, tf_taskstub_get_task_object(parent));
} }
while (task->_promise_count) while (task->_promise_count)
{ {
@ -1911,10 +1917,16 @@ void tf_task_destroy(tf_task_t* task)
uv_run(&task->_loop, UV_RUN_ONCE); uv_run(&task->_loop, UV_RUN_ONCE);
} }
if (uv_loop_close(&task->_loop) != 0) int index = 0;
while (uv_loop_close(&task->_loop) != 0)
{ {
if (index++ > 0)
{
tf_printf("--\n");
uv_print_all_handles(&task->_loop, stdout); uv_print_all_handles(&task->_loop, stdout);
} }
uv_run(&task->_loop, UV_RUN_ONCE);
}
if (task->_trace) if (task->_trace)
{ {
tf_trace_destroy(task->_trace); tf_trace_destroy(task->_trace);

View File

@ -205,7 +205,7 @@ static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int a
JS_FreeValue(context, taskObject); JS_FreeValue(context, taskObject);
} }
} }
return result; return JS_DupValue(context, result);
} }
static void _taskstub_gc_mark(JSRuntime* rt, JSValueConst value, JS_MarkFunc mark_func) static void _taskstub_gc_mark(JSRuntime* rt, JSValueConst value, JS_MarkFunc mark_func)
@ -326,8 +326,8 @@ static void _taskstub_finalizer(JSRuntime* runtime, JSValue value)
static void _taskstub_on_handle_close(uv_handle_t* handle) static void _taskstub_on_handle_close(uv_handle_t* handle)
{ {
tf_taskstub_t* stub = handle->data; tf_taskstub_t* stub = handle->data;
handle->data = NULL;
tf_task_remove_child(stub->_owner, stub); tf_task_remove_child(stub->_owner, stub);
handle->data = NULL;
_taskstub_cleanup(stub); _taskstub_cleanup(stub);
} }
@ -455,9 +455,8 @@ static JSValue _taskstub_execute(JSContext* context, JSValueConst this_val, int
return result; return result;
} }
static JSValue _taskstub_kill(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) JSValue tf_taskstub_kill(tf_taskstub_t* stub)
{ {
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
JSValue result = JS_UNDEFINED; JSValue result = JS_UNDEFINED;
if (!tf_task_get_one_proc(stub->_owner)) if (!tf_task_get_one_proc(stub->_owner))
{ {
@ -472,35 +471,10 @@ static JSValue _taskstub_kill(JSContext* context, JSValueConst this_val, int arg
return result; return result;
} }
void tf_taskstub_destroy(tf_taskstub_t* stub) static JSValue _taskstub_kill(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{ {
JSContext* context = tf_task_get_context(stub->_owner); tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
if (stub->_stream) return tf_taskstub_kill(stub);
{
tf_packetstream_destroy(stub->_stream);
stub->_stream = NULL;
}
if (!JS_IsUndefined(stub->_on_exit))
{
JS_FreeValue(context, stub->_on_exit);
stub->_on_exit = JS_UNDEFINED;
}
if (!JS_IsUndefined(stub->_on_error))
{
JS_FreeValue(context, stub->_on_error);
stub->_on_error = JS_UNDEFINED;
}
if (!JS_IsUndefined(stub->_on_print))
{
JS_FreeValue(context, stub->_on_print);
stub->_on_print = JS_UNDEFINED;
}
if (!JS_IsUndefined(stub->_object))
{
JSValue object = stub->_object;
stub->_object = JS_UNDEFINED;
JS_FreeValue(context, object);
}
} }
void tf_taskstub_on_error(tf_taskstub_t* stub, JSValue error) void tf_taskstub_on_error(tf_taskstub_t* stub, JSValue error)

View File

@ -16,6 +16,5 @@ JSValue tf_taskstub_get_task_object(const tf_taskstub_t* stub);
tf_packetstream_t* tf_taskstub_get_stream(const tf_taskstub_t* stub); tf_packetstream_t* tf_taskstub_get_stream(const tf_taskstub_t* stub);
tf_task_t* tf_taskstub_get_owner(const tf_taskstub_t* stub); tf_task_t* tf_taskstub_get_owner(const tf_taskstub_t* stub);
tf_taskstub_t* tf_taskstub_create_parent(tf_task_t* task, uv_file file); tf_taskstub_t* tf_taskstub_create_parent(tf_task_t* task, uv_file file);
void tf_taskstub_destroy(tf_taskstub_t* stub);
void tf_taskstub_on_error(tf_taskstub_t* stub, JSValue error); void tf_taskstub_on_error(tf_taskstub_t* stub, JSValue error);
void tf_taskstub_on_print(tf_taskstub_t* stub, JSValue arguments); void tf_taskstub_on_print(tf_taskstub_t* stub, JSValue arguments);