Przeglądaj źródła

resource: fix Ctrl+C/SIGINT/SIGTERM not being honored"

Daniele Bartolini 3 lat temu
rodzic
commit
a6ccb64dae

+ 1 - 0
docs/changelog.rst

@@ -8,6 +8,7 @@ Changelog
 **Data Compiler**
 
 * Fixed file changes not detected sometimes.
+* Fixed Ctrl+C/SIGTERM/SIGINT not being honored when launched with --server.
 
 **Runtime**
 

+ 18 - 10
src/device/console_server.cpp

@@ -167,25 +167,32 @@ void ConsoleServer::listen(u16 port, bool wait)
 	_input_thread.start([](void *thiz) { return ((ConsoleServer *)thiz)->run_input_thread(); }, this);
 	_output_thread.start([](void *thiz) { return ((ConsoleServer *)thiz)->run_output_thread(); }, this);
 
+	// Connect a dummy client to the _server to
+	// unlock the input_thread later at exit.
+	_dummy_client.connect(IP_ADDRESS_LOOPBACK, _port);
+	_client_connected.wait();
+
+	// Wait for real clients to connect.
 	if (wait)
 		_client_connected.wait();
 }
 
-void ConsoleServer::shutdown()
+void ConsoleServer::close()
 {
 	_thread_exit = true;
 
-	if (_input_thread.is_running()) {
-		// Unlock input thread if it is stuck waiting for _handlers_semaphore.
-		execute_message_handlers(false);
+	// Unlock input thread if it is stuck inside the select().
+	u32 blank_header = 0;
+	_dummy_client.write(&blank_header, sizeof(blank_header));
+}
 
-		// Unlock input thread if it is stuck inside the select().
-		TCPSocket dummy;
-		dummy.connect(IP_ADDRESS_LOOPBACK, _port);
+void ConsoleServer::shutdown()
+{
+	close();
+	_dummy_client.close();
 
+	if (_input_thread.is_running())
 		_input_thread.stop();
-		dummy.close();
-	}
 
 	_output_condition.signal();
 	if (_output_thread.is_running())
@@ -397,7 +404,8 @@ s32 ConsoleServer::run_input_thread()
 
 		if (array::size(*_input_write) > 0) {
 			_input_semaphore.post();
-			_handlers_semaphore.wait();
+			if (!_thread_exit)
+				_handlers_semaphore.wait();
 		}
 	}
 

+ 4 - 0
src/device/console_server.h

@@ -45,6 +45,7 @@ struct ConsoleServer
 
 	u16 _port;
 	TCPSocket _server;
+	TCPSocket _dummy_client;
 	u32 _next_client_id;
 	Mutex _clients_mutex;
 	Vector<Client> _clients;
@@ -80,6 +81,9 @@ struct ConsoleServer
 	/// blocks until a client is connected.
 	void listen(u16 port, bool wait);
 
+	/// Closes the server.
+	void close();
+
 	/// Shutdowns the server.
 	void shutdown();
 

+ 34 - 16
src/resource/data_compiler.cpp

@@ -1227,25 +1227,43 @@ int main_data_compiler(const DeviceOptions &opts)
 #if CROWN_PLATFORM_WINDOWS
 	// code-format off
 	PHANDLER_ROUTINE signal_handler = [](DWORD dwCtrlType) {
-		switch (dwCtrlType) {
-		case CTRL_C_EVENT:
-			_quit = true;
-			return TRUE;
-
-		default:
-			return FALSE;
-		}
-	};
-	// code-format on
+			switch (dwCtrlType) {
+			case CTRL_C_EVENT:
+				_quit = true;
+				if (console_server())
+					console_server()->close();
+				return TRUE;
+
+			default:
+				return FALSE;
+			}
+		};
 	SetConsoleCtrlHandler(signal_handler, TRUE);
 #else
 	struct sigaction old_SIGINT;
+	struct sigaction old_SIGTERM;
 	struct sigaction act;
-	act.sa_handler = [](int /*signum*/) { _quit = true; };
+	act.sa_handler = [](int signum) {
+			switch (signum)
+			{
+			case SIGINT:
+			case SIGTERM:
+				_quit = true;
+				if (console_server())
+					console_server()->close();
+				break;
+
+			default:
+				break;
+			}
+		};
 	sigemptyset(&act.sa_mask);
 	act.sa_flags = 0;
 	sigaction(SIGINT, NULL, &old_SIGINT);
 	sigaction(SIGINT, &act, NULL);
+	sigaction(SIGTERM, NULL, &old_SIGTERM);
+	sigaction(SIGTERM, &act, NULL);
+	// code-format on
 #endif // if CROWN_PLATFORM_WINDOWS
 
 	console_server_globals::init();
@@ -1327,12 +1345,12 @@ int main_data_compiler(const DeviceOptions &opts)
 	CE_DELETE(default_allocator(), dc);
 	console_server_globals::shutdown();
 
-#if CROWN_PLATFORM_POSIX
-	// Restore original handler
-	sigaction(SIGINT, &old_SIGINT, NULL);
-#elif CROWN_PLATFORM_WINDOWS
-	// Restore original handler
+	// Restore original signal handlers.
+#if CROWN_PLATFORM_WINDOWS
 	SetConsoleCtrlHandler(signal_handler, FALSE);
+#else
+	sigaction(SIGINT, &old_SIGINT, NULL);
+	sigaction(SIGTERM, &old_SIGTERM, NULL);
 #endif
 
 	return success ? EXIT_SUCCESS : EXIT_FAILURE;