Skip to content

Commit ff40b66

Browse files
authored
Port httpserver extension to DuckDB v1.5.4. (#52)
* Port httpserver extension to DuckDB v1.5.4. Update duckdb and extension-ci-tools submodules, pin CI workflows to v1.5.4, and fix a crash in httpserve_start caused by a dangling ExtensionLoader reference. * Fix Linux CI segfault by using synchronous httplib task queue. OpenSSL-enabled httplib runs request handlers in a thread pool by default, which can crash with statically linked OpenSSL on Linux amd64. Handle requests on the server thread instead.
1 parent ecff38e commit ff40b66

4 files changed

Lines changed: 32 additions & 7 deletions

File tree

.github/workflows/MainDistributionPipeline.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ concurrency:
1313
jobs:
1414
duckdb-stable-build:
1515
name: Build extension binaries
16-
uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main
16+
uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5.4
1717
with:
18-
duckdb_version: main
19-
ci_tools_version: main
18+
duckdb_version: v1.5.4
19+
ci_tools_version: v1.5.4
2020
extension_name: httpserver

duckdb

Submodule duckdb updated 4875 files

src/httpserver_extension.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ namespace duckdb
2626

2727
using namespace duckdb_yyjson; // NOLINT(*-build-using-namespace)
2828

29+
// httplib defaults to a thread pool when OpenSSL is enabled. With statically
30+
// linked OpenSSL on Linux this can segfault in worker threads, so handle
31+
// requests synchronously on the server thread instead.
32+
class SynchronousTaskQueue : public duckdb_httplib_openssl::TaskQueue
33+
{
34+
public:
35+
bool enqueue(std::function<void()> fn) override
36+
{
37+
fn();
38+
return true;
39+
}
40+
41+
void shutdown() override
42+
{
43+
}
44+
};
45+
2946
struct HttpServerState
3047
{
3148
std::unique_ptr<duckdb_httplib_openssl::Server> server;
@@ -384,6 +401,12 @@ namespace duckdb
384401
std::string error_message = "DB::Exception: " + std::string(ex.what());
385402
res.set_content(error_message, "text/plain");
386403
}
404+
catch (const std::exception &ex)
405+
{
406+
res.status = 500;
407+
std::string error_message = "DB::Exception: " + std::string(ex.what());
408+
res.set_content(error_message, "text/plain");
409+
}
387410
}
388411

389412
void HttpServerStart(shared_ptr<DatabaseInstance> db, string_t host, int32_t port, string_t auth = string_t())
@@ -395,6 +418,7 @@ namespace duckdb
395418

396419
global_state.db_instance = db;
397420
global_state.server = make_uniq<duckdb_httplib_openssl::Server>();
421+
global_state.server->new_task_queue = []() { return new SynchronousTaskQueue(); };
398422
global_state.is_running = true;
399423
global_state.auth_token = auth.GetString();
400424

@@ -580,9 +604,10 @@ namespace duckdb
580604

581605
static void LoadInternal(ExtensionLoader &loader)
582606
{
607+
auto db = loader.GetDatabaseInstance().shared_from_this();
583608
auto httpserve_start = ScalarFunction(
584609
"httpserve_start", {LogicalType::VARCHAR, LogicalType::INTEGER, LogicalType::VARCHAR}, LogicalType::VARCHAR,
585-
[&](DataChunk &args, ExpressionState &state, Vector &result)
610+
[db](DataChunk &args, ExpressionState &state, Vector &result)
586611
{
587612
auto &host_vector = args.data[0];
588613
auto &port_vector = args.data[1];
@@ -592,7 +617,7 @@ namespace duckdb
592617
{
593618
auto port = ((int32_t *)port_vector.GetData())[0];
594619
auto auth = ((string_t *)auth_vector.GetData())[0];
595-
HttpServerStart(loader.GetDatabaseInstance().shared_from_this(), host, port, auth);
620+
HttpServerStart(db, host, port, auth);
596621
return StringVector::AddString(result, "HTTP server started on " + host.GetString() + ":" +
597622
std::to_string(port)); });
598623
});

0 commit comments

Comments
 (0)