Trying to better understand import/export leaks. Possibly cleaned up after tasks better, but mostly just tweaked counters.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3762 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		@@ -1516,7 +1516,7 @@ static void _tf_ssb_trace_timer(uv_timer_t* timer)
 | 
			
		||||
		ssb->broadcasts_changed_count,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	tf_trace_counter(ssb->trace, "lists", _countof(values), names, values);
 | 
			
		||||
	tf_trace_counter(ssb->trace, "ssb", _countof(values), names, values);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, sqlite3* db, const char* secrets_path)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										127
									
								
								src/task.c
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								src/task.c
									
									
									
									
									
								
							@@ -40,7 +40,8 @@ typedef struct _import_record_t import_record_t;
 | 
			
		||||
 | 
			
		||||
typedef struct _task_child_node_t task_child_node_t;
 | 
			
		||||
 | 
			
		||||
typedef struct _task_child_node_t {
 | 
			
		||||
typedef struct _task_child_node_t
 | 
			
		||||
{
 | 
			
		||||
	taskid_t id;
 | 
			
		||||
	tf_taskstub_t* stub;
 | 
			
		||||
	task_child_node_t* next;
 | 
			
		||||
@@ -48,19 +49,22 @@ typedef struct _task_child_node_t {
 | 
			
		||||
 | 
			
		||||
typedef struct _script_export_t script_export_t;
 | 
			
		||||
 | 
			
		||||
typedef struct _script_export_t {
 | 
			
		||||
typedef struct _script_export_t
 | 
			
		||||
{
 | 
			
		||||
	const char* name;
 | 
			
		||||
	JSValue value;
 | 
			
		||||
	script_export_t* next;
 | 
			
		||||
} script_export_t;
 | 
			
		||||
 | 
			
		||||
typedef struct _promise_t promise_t;
 | 
			
		||||
typedef struct _promise_t {
 | 
			
		||||
typedef struct _promise_t
 | 
			
		||||
{
 | 
			
		||||
	promiseid_t id;
 | 
			
		||||
	JSValue values[3];
 | 
			
		||||
} promise_t;
 | 
			
		||||
 | 
			
		||||
typedef struct _tf_task_t {
 | 
			
		||||
typedef struct _tf_task_t
 | 
			
		||||
{
 | 
			
		||||
	taskid_t _nextTask;
 | 
			
		||||
	task_child_node_t* _children;
 | 
			
		||||
	int _child_count;
 | 
			
		||||
@@ -90,6 +94,7 @@ typedef struct _tf_task_t {
 | 
			
		||||
	int _promise_count;
 | 
			
		||||
	promiseid_t _nextPromise;
 | 
			
		||||
	uv_loop_t _loop;
 | 
			
		||||
	uv_timer_t trace_timer;
 | 
			
		||||
 | 
			
		||||
	export_record_t** _exports;
 | 
			
		||||
	int _export_count;
 | 
			
		||||
@@ -108,7 +113,8 @@ typedef struct _tf_task_t {
 | 
			
		||||
	const char* _args;
 | 
			
		||||
} tf_task_t;
 | 
			
		||||
 | 
			
		||||
typedef struct _export_record_t {
 | 
			
		||||
typedef struct _export_record_t
 | 
			
		||||
{
 | 
			
		||||
	taskid_t _taskid;
 | 
			
		||||
	exportid_t _export_id;
 | 
			
		||||
	JSValue _function;
 | 
			
		||||
@@ -154,7 +160,8 @@ static JSValue _tf_task_executeSource(tf_task_t* task, const char* source, const
 | 
			
		||||
static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id);
 | 
			
		||||
static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId);
 | 
			
		||||
 | 
			
		||||
typedef struct _import_record_t {
 | 
			
		||||
typedef struct _import_record_t
 | 
			
		||||
{
 | 
			
		||||
	tf_task_t* _owner;
 | 
			
		||||
	JSValue _function;
 | 
			
		||||
	exportid_t _export;
 | 
			
		||||
@@ -195,57 +202,44 @@ static import_record_t** _tf_task_find_import(tf_task_t* task, taskid_t task_id,
 | 
			
		||||
	return it;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_task_trace_imports(tf_task_t* task)
 | 
			
		||||
{
 | 
			
		||||
	tf_trace_counter(task->_trace, "imports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_import_count });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _import_record_release(import_record_t** import)
 | 
			
		||||
static bool _import_record_release(import_record_t** import)
 | 
			
		||||
{
 | 
			
		||||
	JSContext* context = (*import)->_owner->_context;
 | 
			
		||||
	tf_task_t* task = (*import)->_owner;
 | 
			
		||||
	import_record_t* record = *import;
 | 
			
		||||
 | 
			
		||||
	if (--record->_useCount > 0)
 | 
			
		||||
	if (--record->_useCount == 0)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		JS_SetOpaque(record->_function, NULL);
 | 
			
		||||
		JS_FreeValue(context, record->_function);
 | 
			
		||||
		record->_function = JS_UNDEFINED;
 | 
			
		||||
		_tf_task_release_export(_tf_task_get_stub(task, record->_task), record->_export);
 | 
			
		||||
 | 
			
		||||
		int index = import - task->_imports;
 | 
			
		||||
		if (task->_import_count - index)
 | 
			
		||||
		{
 | 
			
		||||
			memmove(import, import + 1, sizeof(import_record_t*) * (task->_import_count - index - 1));
 | 
			
		||||
		}
 | 
			
		||||
		task->_import_count--;
 | 
			
		||||
	_tf_task_trace_imports(task);
 | 
			
		||||
 | 
			
		||||
		free(record);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _import_record_release_for_task(tf_task_t* task, taskid_t task_id)
 | 
			
		||||
{
 | 
			
		||||
	bool any = false;
 | 
			
		||||
	for (int i = 0; i < task->_import_count; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (task->_imports[i]->_task == task_id)
 | 
			
		||||
		{
 | 
			
		||||
			_import_record_release(&task->_imports[i]);
 | 
			
		||||
			any = true;
 | 
			
		||||
			while (!_import_record_release(&task->_imports[i]))
 | 
			
		||||
			{
 | 
			
		||||
			}
 | 
			
		||||
			--i;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (any)
 | 
			
		||||
	{
 | 
			
		||||
		_tf_task_trace_imports(task);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_task_trace_exports(tf_task_t* task)
 | 
			
		||||
{
 | 
			
		||||
	tf_trace_counter(task->_trace, "exports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_export_count });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _export_compare(const void* a, const void* b)
 | 
			
		||||
@@ -264,25 +258,18 @@ static int _export_compare(const void* a, const void* b)
 | 
			
		||||
 | 
			
		||||
static void _export_record_release_for_task(tf_task_t* task, taskid_t task_id)
 | 
			
		||||
{
 | 
			
		||||
	bool any = false;
 | 
			
		||||
	for (int i = 0; i < task->_export_count; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (task->_exports[i]->_taskid == task_id)
 | 
			
		||||
		{
 | 
			
		||||
			if (_export_record_release(task, &task->_exports[i]))
 | 
			
		||||
			while (!_export_record_release(task, &task->_exports[i]))
 | 
			
		||||
			{
 | 
			
		||||
				any = true;
 | 
			
		||||
			}
 | 
			
		||||
			i--;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	if (any)
 | 
			
		||||
	{
 | 
			
		||||
		_tf_task_trace_exports(task);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tf_task_send_error_to_parent(tf_task_t* task, JSValue error)
 | 
			
		||||
{
 | 
			
		||||
	if (task && task->_parent)
 | 
			
		||||
@@ -420,6 +407,10 @@ static JSValue _import_call(JSContext* context, JSValueConst func_obj, JSValueCo
 | 
			
		||||
 | 
			
		||||
static export_record_t** _task_get_export(tf_task_t* task, exportid_t export_id)
 | 
			
		||||
{
 | 
			
		||||
	if (!task->_export_count)
 | 
			
		||||
	{
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	export_record_t** it = bsearch(&export_id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare);
 | 
			
		||||
	return it;
 | 
			
		||||
}
 | 
			
		||||
@@ -660,7 +651,6 @@ exportid_t tf_task_export_function(tf_task_t* task, tf_taskstub_t* to, JSValue f
 | 
			
		||||
		}
 | 
			
		||||
		task->_exports[index] = export;
 | 
			
		||||
		task->_export_count++;
 | 
			
		||||
		_tf_task_trace_exports(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (export)
 | 
			
		||||
@@ -683,7 +673,8 @@ static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static JSValue _tf_task_trace(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv){
 | 
			
		||||
static JSValue _tf_task_trace(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
 | 
			
		||||
{
 | 
			
		||||
	tf_task_t* task = JS_GetContextOpaque(context);
 | 
			
		||||
	if (!task->_trace)
 | 
			
		||||
	{
 | 
			
		||||
@@ -1103,11 +1094,6 @@ static promise_t* _tf_task_find_promise(tf_task_t* task, promiseid_t id)
 | 
			
		||||
	return it ? it : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_task_trace_promises(tf_task_t* task)
 | 
			
		||||
{
 | 
			
		||||
	tf_trace_counter(task->_trace, "promises", 1, (const char*[]) { "count" }, (int64_t[]) { task->_promise_count });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_task_free_promise(tf_task_t* task, promiseid_t id)
 | 
			
		||||
{
 | 
			
		||||
	promise_t* it = bsearch((void*)(intptr_t)id, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare);
 | 
			
		||||
@@ -1116,7 +1102,6 @@ static void _tf_task_free_promise(tf_task_t* task, promiseid_t id)
 | 
			
		||||
		int index = it - task->_promises;
 | 
			
		||||
		memmove(it, it + 1, sizeof(promise_t) * (task->_promise_count - index - 1));
 | 
			
		||||
		task->_promise_count--;
 | 
			
		||||
		_tf_task_trace_promises(task);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1141,7 +1126,6 @@ JSValue tf_task_allocate_promise(tf_task_t* task, promiseid_t* out_promise)
 | 
			
		||||
	}
 | 
			
		||||
	task->_promises[index] = promise;
 | 
			
		||||
	task->_promise_count++;
 | 
			
		||||
	_tf_task_trace_promises(task);
 | 
			
		||||
	*out_promise = promiseId;
 | 
			
		||||
	return promise.values[0];
 | 
			
		||||
}
 | 
			
		||||
@@ -1187,11 +1171,6 @@ JSValue tf_task_get_promise(tf_task_t* task, promiseid_t promise)
 | 
			
		||||
	return it ? it->values[0] : JS_NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_task_trace_children(tf_task_t* task)
 | 
			
		||||
{
 | 
			
		||||
	tf_trace_counter(task->_trace, "child_tasks", 1, (const char*[]) { "count" }, (int64_t[]) { task->_child_count });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
taskid_t tf_task_allocate_task_id(tf_task_t* task, tf_taskstub_t* stub)
 | 
			
		||||
{
 | 
			
		||||
	taskid_t id = 0;
 | 
			
		||||
@@ -1208,7 +1187,6 @@ taskid_t tf_task_allocate_task_id(tf_task_t* task, tf_taskstub_t* stub)
 | 
			
		||||
	};
 | 
			
		||||
	task->_children = node;
 | 
			
		||||
	task->_child_count++;
 | 
			
		||||
	_tf_task_trace_children(task);
 | 
			
		||||
	return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1226,7 +1204,6 @@ void tf_task_remove_child(tf_task_t* task, tf_taskstub_t* child)
 | 
			
		||||
			*it = node->next;
 | 
			
		||||
			free(node);
 | 
			
		||||
			task->_child_count--;
 | 
			
		||||
			_tf_task_trace_children(task);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -1259,6 +1236,26 @@ static void _tf_task_promise_rejection_tracker(JSContext* context, JSValueConst
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_task_trace_timer(uv_timer_t* timer)
 | 
			
		||||
{
 | 
			
		||||
	tf_task_t* task = timer->data;
 | 
			
		||||
	const char* k_names[] =
 | 
			
		||||
	{
 | 
			
		||||
		"child_tasks",
 | 
			
		||||
		"imports",
 | 
			
		||||
		"exports",
 | 
			
		||||
		"promises",
 | 
			
		||||
	};
 | 
			
		||||
	int64_t values[] =
 | 
			
		||||
	{
 | 
			
		||||
		task->_child_count,
 | 
			
		||||
		task->_import_count,
 | 
			
		||||
		task->_export_count,
 | 
			
		||||
		task->_promise_count,
 | 
			
		||||
	};
 | 
			
		||||
	tf_trace_counter(task->_trace, "task", sizeof(k_names) / sizeof(*k_names), k_names, values);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tf_task_t* tf_task_create()
 | 
			
		||||
{
 | 
			
		||||
	tf_task_t* task = malloc(sizeof(tf_task_t));
 | 
			
		||||
@@ -1282,6 +1279,10 @@ tf_task_t* tf_task_create()
 | 
			
		||||
	task->_loadedFiles = JS_NewObject(task->_context);
 | 
			
		||||
	uv_loop_init(&task->_loop);
 | 
			
		||||
	task->_loop.data = task;
 | 
			
		||||
	task->trace_timer.data = task;
 | 
			
		||||
	uv_timer_init(&task->_loop, &task->trace_timer);
 | 
			
		||||
	uv_timer_start(&task->trace_timer, _tf_task_trace_timer, 100, 100);
 | 
			
		||||
	uv_unref((uv_handle_t*)&task->trace_timer);
 | 
			
		||||
	return task;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1396,6 +1397,11 @@ JSContext* tf_task_get_context(tf_task_t* task)
 | 
			
		||||
	return task->_context;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_task_on_handle_close(uv_handle_t* handle)
 | 
			
		||||
{
 | 
			
		||||
	handle->data = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tf_task_destroy(tf_task_t* task)
 | 
			
		||||
{
 | 
			
		||||
	for (int i = 0; i < task->_import_count; i++)
 | 
			
		||||
@@ -1461,6 +1467,16 @@ void tf_task_destroy(tf_task_t* task)
 | 
			
		||||
		sqlite3_close(task->_db);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (task->trace_timer.data && !uv_is_closing((uv_handle_t*)&task->trace_timer))
 | 
			
		||||
	{
 | 
			
		||||
		uv_close((uv_handle_t*)&task->trace_timer, _tf_task_on_handle_close);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (task->trace_timer.data)
 | 
			
		||||
	{
 | 
			
		||||
		uv_run(&task->_loop, UV_RUN_ONCE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (uv_loop_close(&task->_loop) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		uv_print_all_handles(&task->_loop, stdout);
 | 
			
		||||
@@ -1492,7 +1508,6 @@ JSValue tf_task_add_import(tf_task_t* task, taskid_t stub_id, exportid_t export_
 | 
			
		||||
	}
 | 
			
		||||
	task->_imports[index] = import;
 | 
			
		||||
	task->_import_count++;
 | 
			
		||||
	_tf_task_trace_imports(task);
 | 
			
		||||
	return function;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user