From c27a9dc138c01f582a919148981eb5bfb983e98a Mon Sep 17 00:00:00 2001 From: Lorenzo Mangani Date: Tue, 15 Oct 2024 15:42:42 +0200 Subject: [PATCH 1/6] Thread Options --- src/httpserver_extension.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/httpserver_extension.cpp b/src/httpserver_extension.cpp index 770bb0b..f034391 100644 --- a/src/httpserver_extension.cpp +++ b/src/httpserver_extension.cpp @@ -383,12 +383,26 @@ void HttpServerStart(DatabaseInstance& db, string_t host, int32_t port, string_t }); string host_str = host.GetString(); - global_state.server_thread = make_uniq([host_str, port]() { + + const char* run_in_same_thread_env = std::getenv("DUCKDB_HTTPSERVER_FOREGROUND"); + bool run_in_same_thread = (run_in_same_thread_env != nullptr && std::string(run_in_same_thread_env) == "1"); + + if (run_in_same_thread) { + // Run the server in the same thread if (!global_state.server->listen(host_str.c_str(), port)) { global_state.is_running = false; throw IOException("Failed to start HTTP server on " + host_str + ":" + std::to_string(port)); } - }); + } else { + // Run the server in a dedicated thread (default) + global_state.server_thread = make_uniq([host_str, port]() { + if (!global_state.server->listen(host_str.c_str(), port)) { + global_state.is_running = false; + throw IOException("Failed to start HTTP server on " + host_str + ":" + std::to_string(port)); + } + }); + } + } void HttpServerStop() { From 80f7eba3473e03fb66128e0dcd4af9281dce477b Mon Sep 17 00:00:00 2001 From: lmangani Date: Wed, 16 Oct 2024 08:54:08 +0000 Subject: [PATCH 2/6] SIGINT handler --- src/httpserver_extension.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/httpserver_extension.cpp b/src/httpserver_extension.cpp index f034391..dcf3b2a 100644 --- a/src/httpserver_extension.cpp +++ b/src/httpserver_extension.cpp @@ -383,16 +383,25 @@ void HttpServerStart(DatabaseInstance& db, string_t host, int32_t port, string_t }); string host_str = host.GetString(); - + const char* run_in_same_thread_env = std::getenv("DUCKDB_HTTPSERVER_FOREGROUND"); bool run_in_same_thread = (run_in_same_thread_env != nullptr && std::string(run_in_same_thread_env) == "1"); if (run_in_same_thread) { + signal(SIGINT, [](int) { + if (global_state.server) { + global_state.server->stop(); + } + }); + // Run the server in the same thread if (!global_state.server->listen(host_str.c_str(), port)) { global_state.is_running = false; throw IOException("Failed to start HTTP server on " + host_str + ":" + std::to_string(port)); } + + // The server has stopped (due to CTRL-C or other reasons) + global_state.is_running = false; } else { // Run the server in a dedicated thread (default) global_state.server_thread = make_uniq([host_str, port]() { From 3cc07ccf6d6aa1d7e55c315d88653c9767a857eb Mon Sep 17 00:00:00 2001 From: Lorenzo Mangani Date: Thu, 17 Oct 2024 15:04:49 +0200 Subject: [PATCH 3/6] Document DUCKDB_HTTPSERVER_FOREGROUND --- docs/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 120470e..b890097 100644 --- a/docs/README.md +++ b/docs/README.md @@ -33,7 +33,8 @@ LOAD httpserver; ### 🔌 Usage Start the HTTP server providing the `host`, `port` and `auth` parameters.
-> If you want no authhentication, just pass an empty string. +> * If you want no authhentication, just pass an empty string as parameter.
+> * If you want the API run in foreground set `DUCKDB_HTTPSERVER_FOREGROUND=1` #### Basic Auth ```sql From a66d9eff60614023ccd4836742700651b1fb22d9 Mon Sep 17 00:00:00 2001 From: Lorenzo Mangani Date: Fri, 18 Oct 2024 16:45:10 +0200 Subject: [PATCH 4/6] Update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index b890097..7b6cca5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -33,7 +33,7 @@ LOAD httpserver; ### 🔌 Usage Start the HTTP server providing the `host`, `port` and `auth` parameters.
-> * If you want no authhentication, just pass an empty string as parameter.
+> * If you want no authentication, just pass an empty string as parameter.
> * If you want the API run in foreground set `DUCKDB_HTTPSERVER_FOREGROUND=1` #### Basic Auth From d6e0d881136b9a505347aa5214b53a99d7afbc05 Mon Sep 17 00:00:00 2001 From: Lorenzo Mangani Date: Sat, 19 Oct 2024 00:02:15 +0200 Subject: [PATCH 5/6] Windows SIGINT handler --- src/httpserver_extension.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/httpserver_extension.cpp b/src/httpserver_extension.cpp index dcf3b2a..c7a4258 100644 --- a/src/httpserver_extension.cpp +++ b/src/httpserver_extension.cpp @@ -388,18 +388,40 @@ void HttpServerStart(DatabaseInstance& db, string_t host, int32_t port, string_t bool run_in_same_thread = (run_in_same_thread_env != nullptr && std::string(run_in_same_thread_env) == "1"); if (run_in_same_thread) { +#ifdef _WIN32 + // Windows-specific handler for Ctrl+C + BOOL WINAPI consoleHandler(DWORD signal) { + if (signal == CTRL_C_EVENT) { + if (global_state.server) { + global_state.server->stop(); + } + global_state.is_running = false; // Update the running state + return TRUE; // Indicate that the signal was handled + } + return FALSE; + } + + // Set the console control handler for Windows + if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) { + std::cerr << "Error setting up signal handler" << std::endl; + throw IOException("Failed to set up signal handler"); + } +#else + // POSIX signal handler for SIGINT (Linux/macOS) signal(SIGINT, [](int) { if (global_state.server) { global_state.server->stop(); } + global_state.is_running = false; // Update the running state }); - +#endif + // Run the server in the same thread if (!global_state.server->listen(host_str.c_str(), port)) { global_state.is_running = false; throw IOException("Failed to start HTTP server on " + host_str + ":" + std::to_string(port)); } - + // The server has stopped (due to CTRL-C or other reasons) global_state.is_running = false; } else { From ecf9362440ed9c77daa5611ce1b651131ab262e7 Mon Sep 17 00:00:00 2001 From: Lorenzo Mangani Date: Sat, 19 Oct 2024 01:26:04 +0200 Subject: [PATCH 6/6] Exclude WIN32 foreground --- src/httpserver_extension.cpp | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/httpserver_extension.cpp b/src/httpserver_extension.cpp index c7a4258..88078f7 100644 --- a/src/httpserver_extension.cpp +++ b/src/httpserver_extension.cpp @@ -389,23 +389,7 @@ void HttpServerStart(DatabaseInstance& db, string_t host, int32_t port, string_t if (run_in_same_thread) { #ifdef _WIN32 - // Windows-specific handler for Ctrl+C - BOOL WINAPI consoleHandler(DWORD signal) { - if (signal == CTRL_C_EVENT) { - if (global_state.server) { - global_state.server->stop(); - } - global_state.is_running = false; // Update the running state - return TRUE; // Indicate that the signal was handled - } - return FALSE; - } - - // Set the console control handler for Windows - if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) { - std::cerr << "Error setting up signal handler" << std::endl; - throw IOException("Failed to set up signal handler"); - } + throw IOException("Foreground mode not yet supported on WIN32 platforms."); #else // POSIX signal handler for SIGINT (Linux/macOS) signal(SIGINT, [](int) { @@ -414,14 +398,14 @@ void HttpServerStart(DatabaseInstance& db, string_t host, int32_t port, string_t } global_state.is_running = false; // Update the running state }); -#endif - + // Run the server in the same thread if (!global_state.server->listen(host_str.c_str(), port)) { global_state.is_running = false; throw IOException("Failed to start HTTP server on " + host_str + ":" + std::to_string(port)); } - +#endif + // The server has stopped (due to CTRL-C or other reasons) global_state.is_running = false; } else {