forked from cory/tildefriends
		
	Make it so we don't have to wait ages for a timer to be able to shutdown with ^C.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4796 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										58
									
								
								src/ssb.c
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								src/ssb.c
									
									
									
									
									
								
							| @@ -173,6 +173,14 @@ typedef struct _tf_thread_work_time_t | |||||||
| 	uint64_t hrtime; | 	uint64_t hrtime; | ||||||
| } tf_thread_work_time_t; | } tf_thread_work_time_t; | ||||||
|  |  | ||||||
|  | typedef struct _tf_ssb_timer_t | ||||||
|  | { | ||||||
|  | 	tf_ssb_t* ssb; | ||||||
|  | 	uv_timer_t timer; | ||||||
|  | 	void (*callback)(tf_ssb_t* ssb, void* user_data); | ||||||
|  | 	void* user_data; | ||||||
|  | } tf_ssb_timer_t; | ||||||
|  |  | ||||||
| typedef struct _tf_ssb_t | typedef struct _tf_ssb_t | ||||||
| { | { | ||||||
| 	bool own_context; | 	bool own_context; | ||||||
| @@ -248,6 +256,9 @@ typedef struct _tf_ssb_t | |||||||
| 	uv_thread_t thread_self; | 	uv_thread_t thread_self; | ||||||
| 	bool is_room; | 	bool is_room; | ||||||
| 	char* room_name; | 	char* room_name; | ||||||
|  |  | ||||||
|  | 	tf_ssb_timer_t** timers; | ||||||
|  | 	int timers_count; | ||||||
| } tf_ssb_t; | } tf_ssb_t; | ||||||
|  |  | ||||||
| typedef struct _tf_ssb_connection_message_request_t | typedef struct _tf_ssb_connection_message_request_t | ||||||
| @@ -2350,6 +2361,11 @@ static void _tf_ssb_on_handle_close(uv_handle_t* handle) | |||||||
| 	handle->data = NULL; | 	handle->data = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void _tf_ssb_on_timer_close(uv_handle_t* handle) | ||||||
|  | { | ||||||
|  | 	tf_free(handle->data); | ||||||
|  | } | ||||||
|  |  | ||||||
| void tf_ssb_destroy(tf_ssb_t* ssb) | void tf_ssb_destroy(tf_ssb_t* ssb) | ||||||
| { | { | ||||||
| 	tf_ssb_connections_destroy(ssb->connections_tracker); | 	tf_ssb_connections_destroy(ssb->connections_tracker); | ||||||
| @@ -2390,6 +2406,14 @@ void tf_ssb_destroy(tf_ssb_t* ssb) | |||||||
| 		uv_close((uv_handle_t*)&ssb->settings_timer, _tf_ssb_on_handle_close); | 		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); | ||||||
|  | 	} | ||||||
|  | 	ssb->timers_count = 0; | ||||||
|  | 	tf_free(ssb->timers); | ||||||
|  | 	ssb->timers = NULL; | ||||||
|  |  | ||||||
| 	while (ssb->broadcast_listener.data || | 	while (ssb->broadcast_listener.data || | ||||||
| 		ssb->broadcast_sender.data || | 		ssb->broadcast_sender.data || | ||||||
| 		ssb->broadcast_timer.data || | 		ssb->broadcast_timer.data || | ||||||
| @@ -3919,3 +3943,37 @@ void tf_ssb_set_verbose(tf_ssb_t* ssb, bool verbose) | |||||||
| { | { | ||||||
| 	ssb->verbose = verbose; | 	ssb->verbose = verbose; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void _tf_ssb_scheduled_timer(uv_timer_t* handle) | ||||||
|  | { | ||||||
|  | 	tf_ssb_timer_t* timer = handle->data; | ||||||
|  | 	timer->callback(timer->ssb, timer->user_data); | ||||||
|  | 	for (int i = 0; i < timer->ssb->timers_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (timer->ssb->timers[i] == timer) | ||||||
|  | 		{ | ||||||
|  | 			timer->ssb->timers[i] = timer->ssb->timers[--timer->ssb->timers_count]; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	uv_close((uv_handle_t*)handle, _tf_ssb_on_timer_close); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void tf_ssb_schedule_work(tf_ssb_t* ssb, int delay_ms, void (*callback)(tf_ssb_t* ssb, void* user_data), void* user_data) | ||||||
|  | { | ||||||
|  | 	ssb->timers = tf_resize_vec(ssb->timers, sizeof(uv_timer_t*) * (ssb->timers_count + 1)); | ||||||
|  | 	tf_ssb_timer_t* timer = tf_malloc(sizeof(tf_ssb_timer_t)); | ||||||
|  | 	*timer = (tf_ssb_timer_t) | ||||||
|  | 	{ | ||||||
|  | 		.ssb = ssb, | ||||||
|  | 		.timer = | ||||||
|  | 		{ | ||||||
|  | 			.data = timer, | ||||||
|  | 		}, | ||||||
|  | 		.callback = callback, | ||||||
|  | 		.user_data = user_data, | ||||||
|  | 	}; | ||||||
|  | 	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); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -225,3 +225,5 @@ bool tf_ssb_is_room(tf_ssb_t* ssb); | |||||||
| void tf_ssb_set_is_room(tf_ssb_t* ssb, bool is_room); | void tf_ssb_set_is_room(tf_ssb_t* ssb, bool is_room); | ||||||
| const char* tf_ssb_get_room_name(tf_ssb_t* ssb); | const char* tf_ssb_get_room_name(tf_ssb_t* ssb); | ||||||
| void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name); | void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name); | ||||||
|  |  | ||||||
|  | void tf_ssb_schedule_work(tf_ssb_t* ssb, int delay_ms, void (*callback)(tf_ssb_t* ssb, void* user_data), void* user_data); | ||||||
|   | |||||||
| @@ -1333,18 +1333,11 @@ 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) | static void _tf_ssb_rpc_delete_blobs_after_work(uv_work_t* work, int status) | ||||||
| { | { | ||||||
| 	delete_blobs_work_t* delete = work->data; | 	delete_blobs_work_t* delete = work->data; | ||||||
| 	tf_ssb_unref(delete->ssb); |  | ||||||
| 	tf_free(delete); | 	tf_free(delete); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void _tf_ssb_rpc_timer_on_close(uv_handle_t* handle) | static void _tf_ssb_rpc_start_delete_callback(tf_ssb_t* ssb, void* user_data) | ||||||
| { | { | ||||||
| 	tf_free(handle); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void _tf_ssb_rpc_start_delete_timer(uv_timer_t* timer) |  | ||||||
| { |  | ||||||
| 	tf_ssb_t* ssb = timer->data; |  | ||||||
| 	delete_blobs_work_t* work = tf_malloc(sizeof(delete_blobs_work_t)); | 	delete_blobs_work_t* work = tf_malloc(sizeof(delete_blobs_work_t)); | ||||||
| 	*work = (delete_blobs_work_t) { .work = { .data = work}, .ssb = ssb }; | 	*work = (delete_blobs_work_t) { .work = { .data = work}, .ssb = 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); | 	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); | ||||||
| @@ -1353,17 +1346,12 @@ static void _tf_ssb_rpc_start_delete_timer(uv_timer_t* timer) | |||||||
| 		tf_printf("uv_queue_work: %s\n", uv_strerror(r)); | 		tf_printf("uv_queue_work: %s\n", uv_strerror(r)); | ||||||
| 		tf_free(work); | 		tf_free(work); | ||||||
| 	} | 	} | ||||||
| 	uv_close((uv_handle_t*)timer, _tf_ssb_rpc_timer_on_close); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void _tf_ssb_rpc_start_delete_blobs(tf_ssb_t* ssb, int delay_ms) | static void _tf_ssb_rpc_start_delete_blobs(tf_ssb_t* ssb, int delay_ms) | ||||||
| { | { | ||||||
| 	tf_printf("will delete more blobs in %d ms\n", delay_ms); | 	tf_printf("will delete more blobs in %d ms\n", delay_ms); | ||||||
| 	uv_timer_t* timer = tf_malloc(sizeof(uv_timer_t)); | 	tf_ssb_schedule_work(ssb, delay_ms, _tf_ssb_rpc_start_delete_callback, NULL); | ||||||
| 	*timer = (uv_timer_t) { .data = ssb }; |  | ||||||
| 	uv_timer_init(tf_ssb_get_loop(ssb), timer); |  | ||||||
| 	uv_timer_start(timer, _tf_ssb_rpc_start_delete_timer, delay_ms, 0); |  | ||||||
| 	tf_ssb_ref(ssb); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void tf_ssb_rpc_start_periodic(tf_ssb_t* ssb) | void tf_ssb_rpc_start_periodic(tf_ssb_t* ssb) | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								src/task.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/task.c
									
									
									
									
									
								
							| @@ -123,7 +123,8 @@ typedef struct _tf_task_t | |||||||
|  |  | ||||||
| 	uv_idle_t idle; | 	uv_idle_t idle; | ||||||
| 	uv_prepare_t prepare; | 	uv_prepare_t prepare; | ||||||
| 	uv_signal_t signal; | 	uv_signal_t sig_term; | ||||||
|  | 	uv_signal_t sig_int; | ||||||
|  |  | ||||||
| 	export_record_t** _exports; | 	export_record_t** _exports; | ||||||
| 	int _export_count; | 	int _export_count; | ||||||
| @@ -1571,8 +1572,9 @@ JSModuleDef* _tf_task_module_loader(JSContext* context, const char* module_name, | |||||||
| 	return module; | 	return module; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void _tf_task_sigterm(uv_signal_t* signal, int sig) | static void _tf_task_signal_shutdown(uv_signal_t* signal, int sig) | ||||||
| { | { | ||||||
|  | 	tf_printf("Received %s.\n", strsignal(sig)); | ||||||
| 	tf_task_t* task = signal->data; | 	tf_task_t* task = signal->data; | ||||||
| 	task->_killed = true; | 	task->_killed = true; | ||||||
| 	if (task->_parent) | 	if (task->_parent) | ||||||
| @@ -1626,10 +1628,14 @@ tf_task_t* tf_task_create() | |||||||
| 	uv_prepare_init(&task->_loop, &task->prepare); | 	uv_prepare_init(&task->_loop, &task->prepare); | ||||||
| 	uv_unref((uv_handle_t*)&task->prepare); | 	uv_unref((uv_handle_t*)&task->prepare); | ||||||
| 	uv_idle_start(&task->idle, _tf_task_run_jobs_idle); | 	uv_idle_start(&task->idle, _tf_task_run_jobs_idle); | ||||||
| 	task->signal.data = task; | 	task->sig_term.data = task; | ||||||
| 	uv_signal_init(&task->_loop, &task->signal); | 	uv_signal_init(&task->_loop, &task->sig_term); | ||||||
| 	uv_signal_start(&task->signal, _tf_task_sigterm, SIGTERM); | 	uv_signal_start(&task->sig_term, _tf_task_signal_shutdown, SIGTERM); | ||||||
| 	uv_unref((uv_handle_t*)&task->signal); | 	uv_unref((uv_handle_t*)&task->sig_term); | ||||||
|  | 	task->sig_int.data = task; | ||||||
|  | 	uv_signal_init(&task->_loop, &task->sig_int); | ||||||
|  | 	uv_signal_start(&task->sig_int, _tf_task_signal_shutdown, SIGINT); | ||||||
|  | 	uv_unref((uv_handle_t*)&task->sig_int); | ||||||
| 	return task; | 	return task; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1857,14 +1863,17 @@ void tf_task_destroy(tf_task_t* task) | |||||||
| 	} | 	} | ||||||
| 	uv_close((uv_handle_t*)&task->idle, _tf_task_on_handle_close); | 	uv_close((uv_handle_t*)&task->idle, _tf_task_on_handle_close); | ||||||
| 	uv_close((uv_handle_t*)&task->prepare, _tf_task_on_handle_close); | 	uv_close((uv_handle_t*)&task->prepare, _tf_task_on_handle_close); | ||||||
| 	uv_signal_stop(&task->signal); | 	uv_signal_stop(&task->sig_term); | ||||||
| 	uv_close((uv_handle_t*)&task->signal, _tf_task_on_handle_close); | 	uv_close((uv_handle_t*)&task->sig_term, _tf_task_on_handle_close); | ||||||
|  | 	uv_signal_stop(&task->sig_int); | ||||||
|  | 	uv_close((uv_handle_t*)&task->sig_int, _tf_task_on_handle_close); | ||||||
|  |  | ||||||
| 	while (task->trace_timer.data || | 	while (task->trace_timer.data || | ||||||
| 		task->gc_timer.data || | 		task->gc_timer.data || | ||||||
| 		task->idle.data || | 		task->idle.data || | ||||||
| 		task->prepare.data || | 		task->prepare.data || | ||||||
| 		task->signal.data) | 		task->sig_term.data || | ||||||
|  | 		task->sig_int.data) | ||||||
| 	{ | 	{ | ||||||
| 		uv_run(&task->_loop, UV_RUN_ONCE); | 		uv_run(&task->_loop, UV_RUN_ONCE); | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user