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
This commit is contained in:
parent
d550092bd3
commit
23b15a8dc5
@ -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_t* task = tf_task_create();
|
||||||
tf_task_configure_from_stdin(task);
|
tf_task_configure_from_stdin(task);
|
||||||
shedPrivileges();
|
shedPrivileges();
|
||||||
tf_task_activate(task);
|
/* The caller will trigger tf_task_activate with a message. */
|
||||||
tf_task_run(task);
|
tf_task_run(task);
|
||||||
tf_task_destroy(task);
|
tf_task_destroy(task);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -105,7 +105,7 @@ static void _packetstream_on_write(uv_write_t* request, int status)
|
|||||||
free(request);
|
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;
|
size_t buffer_length = sizeof(uv_write_t) + sizeof(packet_type) + sizeof(length) + length;
|
||||||
uv_write_t* request = malloc(buffer_length);
|
uv_write_t* request = malloc(buffer_length);
|
||||||
|
@ -12,7 +12,7 @@ tf_packetstream_t* tf_packetstream_create();
|
|||||||
void tf_packetstream_destroy(tf_packetstream_t* stream);
|
void tf_packetstream_destroy(tf_packetstream_t* stream);
|
||||||
|
|
||||||
void tf_packetstream_start(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_set_on_receive(tf_packetstream_t* stream, tf_packetstream_onreceive_t* callback, void* user_data);
|
||||||
void tf_packetstream_close(tf_packetstream_t* stream);
|
void tf_packetstream_close(tf_packetstream_t* stream);
|
||||||
uv_pipe_t* tf_packetstream_get_pipe(tf_packetstream_t* stream);
|
uv_pipe_t* tf_packetstream_get_pipe(tf_packetstream_t* stream);
|
||||||
|
31
src/task.c
31
src/task.c
@ -71,6 +71,7 @@ typedef struct _tf_task_t {
|
|||||||
|
|
||||||
script_export_t* _scriptExports;
|
script_export_t* _scriptExports;
|
||||||
|
|
||||||
|
bool _activated;
|
||||||
bool _trusted;
|
bool _trusted;
|
||||||
bool _killed;
|
bool _killed;
|
||||||
int32_t _exitCode;
|
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);
|
export_record_t* export = _task_get_export(to, exportId);
|
||||||
if (export)
|
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* argument_array = NULL;
|
||||||
JSValue length_val = JS_GetPropertyStr(to->_context, arguments, "length");
|
JSValue length_val = JS_GetPropertyStr(to->_context, arguments, "length");
|
||||||
int 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));
|
memcpy(&promise, begin, sizeof(promiseid_t));
|
||||||
if (length > 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)
|
if (packetType == kResolvePromise)
|
||||||
{
|
{
|
||||||
@ -731,11 +732,11 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kSetRequires:
|
case kSetRequires:
|
||||||
to->_requires = tf_serialize_load((tf_task_t*)to, from, begin, length);
|
to->_requires = tf_serialize_load(to, from, begin, length);
|
||||||
break;
|
break;
|
||||||
case kLoadFile:
|
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 key = JS_GetPropertyUint32(to->_context, args, 0);
|
||||||
JSValue content = JS_GetPropertyUint32(to->_context, args, 1);
|
JSValue content = JS_GetPropertyUint32(to->_context, args, 1);
|
||||||
const char* name = JS_ToCString(to->_context, key);
|
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));
|
assert(length >= sizeof(promiseid_t));
|
||||||
promiseid_t promise;
|
promiseid_t promise;
|
||||||
memcpy(&promise, begin, sizeof(promiseid_t));
|
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 source = JS_GetPropertyStr(to->_context, value, "source");
|
||||||
JSValue name_val = JS_GetPropertyStr(to->_context, value, "name");
|
JSValue name_val = JS_GetPropertyStr(to->_context, value, "name");
|
||||||
const char* name = JS_ToCString(to->_context, name_val);
|
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:
|
case kSetImports:
|
||||||
{
|
{
|
||||||
JSValue global = JS_GetGlobalObject(to->_context);
|
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;
|
JSPropertyEnum* ptab;
|
||||||
uint32_t plen;
|
uint32_t plen;
|
||||||
@ -810,11 +811,14 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length,
|
|||||||
break;
|
break;
|
||||||
case kTaskError:
|
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);
|
tf_taskstub_on_error(from, error);
|
||||||
JS_FreeValue(to->_context, error);
|
JS_FreeValue(to->_context, error);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case kTaskTrace:
|
||||||
|
tf_trace_raw(to->_trace, begin, length);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
tf_trace_end(to->_trace);
|
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);
|
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)
|
void tf_task_activate(tf_task_t* task)
|
||||||
{
|
{
|
||||||
|
assert(!task->_activated);
|
||||||
|
task->_activated = true;
|
||||||
|
|
||||||
JSContext* context = task->_context;
|
JSContext* context = task->_context;
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
JSValue global = JS_GetGlobalObject(context);
|
||||||
JS_SetPropertyStr(context, global, "exports", JS_NewObject(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);
|
JS_SetPropertyStr(context, global, "tildefriends", tildefriends);
|
||||||
|
|
||||||
|
task->_trace = tf_trace_create();
|
||||||
if (task->_trusted)
|
if (task->_trusted)
|
||||||
{
|
{
|
||||||
sqlite3_open(*task->_db_path ? task->_db_path : "db.sqlite", &task->_db);
|
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));
|
JS_SetPropertyStr(context, global, "TlsContext", tf_tls_context_register(context));
|
||||||
tf_file_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);
|
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_set_trace(task->_ssb, task->_trace);
|
||||||
tf_ssb_register(context, task->_ssb);
|
tf_ssb_register(context, task->_ssb);
|
||||||
@ -1297,6 +1309,7 @@ void tf_task_activate(tf_task_t* task)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
JS_SetPropertyStr(context, global, "require", JS_NewCFunction(context, _tf_task_sandbox_require, "sandboxRequire", 0));
|
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);
|
tf_bcrypt_register(context);
|
||||||
|
@ -31,6 +31,7 @@ typedef enum _tf_task_message_t {
|
|||||||
kGetExports,
|
kGetExports,
|
||||||
kLoadFile,
|
kLoadFile,
|
||||||
kTaskError,
|
kTaskError,
|
||||||
|
kTaskTrace,
|
||||||
} tf_task_message_t;
|
} tf_task_message_t;
|
||||||
|
|
||||||
tf_task_t* tf_task_create();
|
tf_task_t* tf_task_create();
|
||||||
|
60
src/trace.c
60
src/trace.c
@ -12,7 +12,8 @@
|
|||||||
#define _countof(a) ((int)(sizeof((a)) / sizeof(*(a))))
|
#define _countof(a) ((int)(sizeof((a)) / sizeof(*(a))))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
enum
|
||||||
|
{
|
||||||
k_buffer_size = 4 * 1024 * 1024,
|
k_buffer_size = 4 * 1024 * 1024,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,13 +31,33 @@ typedef struct _tf_trace_t
|
|||||||
char buffer[k_buffer_size];
|
char buffer[k_buffer_size];
|
||||||
int write_offset;
|
int write_offset;
|
||||||
|
|
||||||
|
tf_trace_write_callback_t* callback;
|
||||||
|
void* user_data;
|
||||||
|
|
||||||
tf_trace_stack_t* stack;
|
tf_trace_stack_t* stack;
|
||||||
} tf_trace_t;
|
} 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* tf_trace_create()
|
||||||
{
|
{
|
||||||
tf_trace_t* trace = malloc(sizeof(tf_trace_t));
|
tf_trace_t* trace = malloc(sizeof(tf_trace_t));
|
||||||
memset(trace, 0, sizeof(*trace));
|
memset(trace, 0, sizeof(*trace));
|
||||||
|
trace->callback = _trace_append;
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +72,11 @@ void tf_trace_destroy(tf_trace_t* trace)
|
|||||||
free(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()
|
static int64_t _trace_ts()
|
||||||
{
|
{
|
||||||
int64_t result = 0;
|
int64_t result = 0;
|
||||||
@ -62,22 +88,6 @@ static int64_t _trace_ts()
|
|||||||
return result;
|
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)
|
void tf_trace_counter(tf_trace_t* trace, const char* name, int argc, const char** arg_names, const int64_t* arg_values)
|
||||||
{
|
{
|
||||||
if (!trace)
|
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 ? "}}," : ", ");
|
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)
|
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, "\"},");
|
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)
|
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];
|
name = stack->names[stack->count - 1];
|
||||||
stack->count--;
|
stack->count--;
|
||||||
}
|
}
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char line[1024];
|
char line[1024];
|
||||||
int p = snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"tid\": 0, \"ts\": %" PRId64 ", \"name\": \"", getpid(), _trace_ts());
|
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, "\"},");
|
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)
|
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;
|
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)
|
void tf_trace_sqlite(tf_trace_t* trace, sqlite3* sqlite)
|
||||||
{
|
{
|
||||||
if (sqlite)
|
if (sqlite)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
typedef struct _tf_trace_t tf_trace_t;
|
typedef struct _tf_trace_t tf_trace_t;
|
||||||
typedef struct sqlite3 sqlite3;
|
typedef struct sqlite3 sqlite3;
|
||||||
@ -14,4 +15,8 @@ void tf_trace_end(tf_trace_t* trace);
|
|||||||
|
|
||||||
char* tf_trace_export(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);
|
void tf_trace_sqlite(tf_trace_t* trace, sqlite3* sqlite);
|
||||||
|
Loading…
Reference in New Issue
Block a user