From 23b15a8dc59b6ecfe5f6fabe061fb3d3b1eec0ba Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Sun, 2 Jan 2022 18:17:58 +0000 Subject: [PATCH] Child processes send trace information back to the parent. Also fixed weird double-activation of children. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3729 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- src/main.c | 2 +- src/packetstream.c | 2 +- src/packetstream.h | 2 +- src/task.c | 31 +++++++++++++++++------- src/task.h | 1 + src/trace.c | 60 ++++++++++++++++++++++++++++++---------------- src/trace.h | 5 ++++ 7 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/main.c b/src/main.c index bae46cb0..4cb58a98 100644 --- a/src/main.c +++ b/src/main.c @@ -481,7 +481,7 @@ static int _tf_command_sandbox(const char* file, int argc, char* argv[]) tf_task_t* task = tf_task_create(); tf_task_configure_from_stdin(task); shedPrivileges(); - tf_task_activate(task); + /* The caller will trigger tf_task_activate with a message. */ tf_task_run(task); tf_task_destroy(task); return 0; diff --git a/src/packetstream.c b/src/packetstream.c index 1004f8d1..d45ce030 100644 --- a/src/packetstream.c +++ b/src/packetstream.c @@ -105,7 +105,7 @@ static void _packetstream_on_write(uv_write_t* request, int status) free(request); } -void tf_packetstream_send(tf_packetstream_t* stream, int packet_type, char* begin, size_t length) +void tf_packetstream_send(tf_packetstream_t* stream, int packet_type, const char* begin, size_t length) { size_t buffer_length = sizeof(uv_write_t) + sizeof(packet_type) + sizeof(length) + length; uv_write_t* request = malloc(buffer_length); diff --git a/src/packetstream.h b/src/packetstream.h index c5851157..512ef5ba 100644 --- a/src/packetstream.h +++ b/src/packetstream.h @@ -12,7 +12,7 @@ tf_packetstream_t* tf_packetstream_create(); void tf_packetstream_destroy(tf_packetstream_t* stream); void tf_packetstream_start(tf_packetstream_t* stream); -void tf_packetstream_send(tf_packetstream_t* stream, int packet_type, char* begin, size_t length); +void tf_packetstream_send(tf_packetstream_t* stream, int packet_type, const char* begin, size_t length); void tf_packetstream_set_on_receive(tf_packetstream_t* stream, tf_packetstream_onreceive_t* callback, void* user_data); void tf_packetstream_close(tf_packetstream_t* stream); uv_pipe_t* tf_packetstream_get_pipe(tf_packetstream_t* stream); diff --git a/src/task.c b/src/task.c index 977e66f9..1407b8ae 100644 --- a/src/task.c +++ b/src/task.c @@ -71,6 +71,7 @@ typedef struct _tf_task_t { script_export_t* _scriptExports; + bool _activated; bool _trusted; bool _killed; int32_t _exitCode; @@ -398,7 +399,7 @@ JSValue _task_invokeExport_internal(tf_taskstub_t* from, tf_task_t* to, exportid export_record_t* export = _task_get_export(to, exportId); if (export) { - JSValue arguments = tf_serialize_load((tf_task_t*)to, from, buffer, size); + JSValue arguments = tf_serialize_load(to, from, buffer, size); JSValue* argument_array = NULL; JSValue length_val = JS_GetPropertyStr(to->_context, arguments, "length"); int length; @@ -678,7 +679,7 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length, memcpy(&promise, begin, sizeof(promiseid_t)); if (length > sizeof(promiseid_t)) { - arg = tf_serialize_load((tf_task_t*)to, from, begin + sizeof(promiseid_t), length - sizeof(promiseid_t)); + arg = tf_serialize_load(to, from, begin + sizeof(promiseid_t), length - sizeof(promiseid_t)); } if (packetType == kResolvePromise) { @@ -731,11 +732,11 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length, } break; case kSetRequires: - to->_requires = tf_serialize_load((tf_task_t*)to, from, begin, length); + to->_requires = tf_serialize_load(to, from, begin, length); break; case kLoadFile: { - JSValue args = tf_serialize_load((tf_task_t*)to, from, begin, length); + JSValue args = tf_serialize_load(to, from, begin, length); JSValue key = JS_GetPropertyUint32(to->_context, args, 0); JSValue content = JS_GetPropertyUint32(to->_context, args, 1); const char* name = JS_ToCString(to->_context, key); @@ -754,7 +755,7 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length, assert(length >= sizeof(promiseid_t)); promiseid_t promise; memcpy(&promise, begin, sizeof(promiseid_t)); - JSValue value = tf_serialize_load((tf_task_t*)to, from, begin + sizeof(promiseid_t), length - sizeof(promiseid_t)); + JSValue value = tf_serialize_load(to, from, begin + sizeof(promiseid_t), length - sizeof(promiseid_t)); JSValue source = JS_GetPropertyStr(to->_context, value, "source"); JSValue name_val = JS_GetPropertyStr(to->_context, value, "name"); const char* name = JS_ToCString(to->_context, name_val); @@ -776,7 +777,7 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length, case kSetImports: { JSValue global = JS_GetGlobalObject(to->_context); - JSValue imports = tf_serialize_load((tf_task_t*)to, from, begin, length); + JSValue imports = tf_serialize_load(to, from, begin, length); JSPropertyEnum* ptab; uint32_t plen; @@ -810,11 +811,14 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length, break; case kTaskError: { - JSValue error = tf_serialize_load((tf_task_t*)to, from, begin, length); + JSValue error = tf_serialize_load(to, from, begin, length); tf_taskstub_on_error(from, error); JS_FreeValue(to->_context, error); } break; + case kTaskTrace: + tf_trace_raw(to->_trace, begin, length); + break; } tf_trace_end(to->_trace); } @@ -1225,8 +1229,17 @@ void tf_task_configure_from_stdin(tf_task_t* task) task->_parent = tf_taskstub_create_parent(task, STDIN_FILENO); } +static void _tf_task_trace_to_parent(tf_trace_t* trace, const char* buffer, size_t size, void* user_data) +{ + tf_task_t* task = user_data; + tf_packetstream_send(tf_taskstub_get_stream(task->_parent), kTaskTrace, buffer, size); +} + void tf_task_activate(tf_task_t* task) { + assert(!task->_activated); + task->_activated = true; + JSContext* context = task->_context; JSValue global = JS_GetGlobalObject(context); JS_SetPropertyStr(context, global, "exports", JS_NewObject(context)); @@ -1270,6 +1283,7 @@ void tf_task_activate(tf_task_t* task) } JS_SetPropertyStr(context, global, "tildefriends", tildefriends); + task->_trace = tf_trace_create(); if (task->_trusted) { sqlite3_open(*task->_db_path ? task->_db_path : "db.sqlite", &task->_db); @@ -1280,8 +1294,6 @@ void tf_task_activate(tf_task_t* task) JS_SetPropertyStr(context, global, "TlsContext", tf_tls_context_register(context)); tf_file_register(context); - task->_trace = tf_trace_create(); - task->_ssb = tf_ssb_create(&task->_loop, task->_context, task->_db, *task->_secrets_path ? task->_secrets_path : NULL); tf_ssb_set_trace(task->_ssb, task->_trace); tf_ssb_register(context, task->_ssb); @@ -1297,6 +1309,7 @@ void tf_task_activate(tf_task_t* task) else { JS_SetPropertyStr(context, global, "require", JS_NewCFunction(context, _tf_task_sandbox_require, "sandboxRequire", 0)); + tf_trace_set_write_callback(task->_trace, _tf_task_trace_to_parent, task); } tf_bcrypt_register(context); diff --git a/src/task.h b/src/task.h index 92edc512..a1721609 100644 --- a/src/task.h +++ b/src/task.h @@ -31,6 +31,7 @@ typedef enum _tf_task_message_t { kGetExports, kLoadFile, kTaskError, + kTaskTrace, } tf_task_message_t; tf_task_t* tf_task_create(); diff --git a/src/trace.c b/src/trace.c index c3a1458c..8d205a72 100644 --- a/src/trace.c +++ b/src/trace.c @@ -12,7 +12,8 @@ #define _countof(a) ((int)(sizeof((a)) / sizeof(*(a)))) #endif -enum { +enum +{ k_buffer_size = 4 * 1024 * 1024, }; @@ -30,13 +31,33 @@ typedef struct _tf_trace_t char buffer[k_buffer_size]; int write_offset; + tf_trace_write_callback_t* callback; + void* user_data; + tf_trace_stack_t* stack; } tf_trace_t; +static void _trace_append(tf_trace_t* trace, const char* buffer, size_t size, void* user_data) +{ + if (trace->write_offset + size + 2 >= k_buffer_size) + { + trace->buffer[trace->write_offset] = '\0'; + trace->write_offset = 0; + } + + if (trace->write_offset + size + 2 < k_buffer_size) + { + memcpy(trace->buffer + trace->write_offset, buffer, size); + trace->write_offset += size; + trace->buffer[trace->write_offset++] = '\n'; + } +} + tf_trace_t* tf_trace_create() { tf_trace_t* trace = malloc(sizeof(tf_trace_t)); memset(trace, 0, sizeof(*trace)); + trace->callback = _trace_append; return trace; } @@ -51,6 +72,11 @@ void tf_trace_destroy(tf_trace_t* trace) free(trace); } +void tf_trace_raw(tf_trace_t* trace, const char* buffer, size_t size) +{ + trace->callback(trace, buffer, size, trace->user_data); +} + static int64_t _trace_ts() { int64_t result = 0; @@ -62,22 +88,6 @@ static int64_t _trace_ts() return result; } -static void _trace_append(tf_trace_t* trace, const char* buffer, size_t size) -{ - if (trace->write_offset + size + 2 >= k_buffer_size) - { - trace->buffer[trace->write_offset] = '\0'; - trace->write_offset = 0; - } - - if (trace->write_offset + size + 2 < k_buffer_size) - { - memcpy(trace->buffer + trace->write_offset, buffer, size); - trace->write_offset += size; - trace->buffer[trace->write_offset++] = '\n'; - } -} - void tf_trace_counter(tf_trace_t* trace, const char* name, int argc, const char** arg_names, const int64_t* arg_values) { if (!trace) @@ -93,7 +103,7 @@ void tf_trace_counter(tf_trace_t* trace, const char* name, int argc, const char* p += snprintf(line + p, sizeof(line) - p, "\"%s\": %" PRId64 "%s", arg_names[i], arg_values[i], i == argc - 1 ? "}}," : ", "); } - _trace_append(trace, line, p); + trace->callback(trace, line, p, trace->user_data); } void tf_trace_begin(tf_trace_t* trace, const char* name) @@ -137,7 +147,7 @@ void tf_trace_begin(tf_trace_t* trace, const char* name) } } p += snprintf(line + p, sizeof(line) - p, "\"},"); - _trace_append(trace, line, p); + trace->callback(trace, line, p, trace->user_data); } void tf_trace_end(tf_trace_t* trace) @@ -158,6 +168,10 @@ void tf_trace_end(tf_trace_t* trace) name = stack->names[stack->count - 1]; stack->count--; } + if (!name) + { + return; + } char line[1024]; int p = snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"tid\": 0, \"ts\": %" PRId64 ", \"name\": \"", getpid(), _trace_ts()); @@ -179,7 +193,7 @@ void tf_trace_end(tf_trace_t* trace) } } p += snprintf(line + p, sizeof(line) - p, "\"},"); - _trace_append(trace, line, p); + trace->callback(trace, line, p, trace->user_data); } char* tf_trace_export(tf_trace_t* trace) @@ -235,6 +249,12 @@ static int _tf_trace_sqlite_callback(unsigned int t, void* c, void* p, void* x) return 0; } +void tf_trace_set_write_callback(tf_trace_t* trace, tf_trace_write_callback_t* callback, void* user_data) +{ + trace->callback = callback; + trace->user_data = user_data; +} + void tf_trace_sqlite(tf_trace_t* trace, sqlite3* sqlite) { if (sqlite) diff --git a/src/trace.h b/src/trace.h index 109a4981..53a0936e 100644 --- a/src/trace.h +++ b/src/trace.h @@ -1,6 +1,7 @@ #pragma once #include +#include typedef struct _tf_trace_t tf_trace_t; typedef struct sqlite3 sqlite3; @@ -14,4 +15,8 @@ void tf_trace_end(tf_trace_t* trace); char* tf_trace_export(tf_trace_t* trace); +typedef void (tf_trace_write_callback_t)(tf_trace_t* trace, const char* buffer, size_t size, void* user_data); +void tf_trace_set_write_callback(tf_trace_t* trace, tf_trace_write_callback_t* callback, void* user_data); +void tf_trace_raw(tf_trace_t* trace, const char* buffer, size_t size); + void tf_trace_sqlite(tf_trace_t* trace, sqlite3* sqlite);