From 7949cd5f12eb7cc0dc85fd1b5c1d795fad1df922 Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Tue, 7 Apr 2026 16:43:56 -0400 Subject: [PATCH] libcephsqlite: ensure atexit handlers are registered after openssl When the sqlite3 executable encounters an error with .bail=on, it will make a call to exit(). The atexit() handlers will execute in LIFO order. We need to ensure that openssl (before OpenSSL 4.0 [1]) atexit handlers are registered before libcephsqlite. [1] http://github.com/openssl/openssl/commit/31659fe32673a6bd66abf3f8a7d803e81c6ffeed (OpenSSL 4.0 no longer arms `OPENSSL_cleanup()` function as an `atexit(3)`) Fixes: https://tracker.ceph.com/issues/59335 Signed-off-by: Patrick Donnelly --- src/libcephsqlite.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libcephsqlite.cc b/src/libcephsqlite.cc index c386271b4e89..afafe6a0d7b6 100644 --- a/src/libcephsqlite.cc +++ b/src/libcephsqlite.cc @@ -90,6 +90,8 @@ enum { using cctptr = boost::intrusive_ptr; using rsptr = std::shared_ptr; +static void cephsqlite_atexit(); + struct cephsqlite_appdata { ~cephsqlite_appdata() { { @@ -212,12 +214,18 @@ private: lderr(cct) << "cannot connect: " << cpp_strerror(rc) << dendl; return rc; } + /* This **must** occur after OpenSSL registers any atexit handlers (**sigh**). */ + std::call_once(atexit_registered, []() { + std::atexit(cephsqlite_atexit); + }); auto s = _cluster->get_addrs(); ldout(cct, 5) << "completed connection to RADOS with address " << s << dendl; cluster = std::move(_cluster); + return 0; } + std::once_flag atexit_registered; ceph::mutex cluster_mutex = ceph::make_mutex("libcephsqlite");; cctptr cct; rsptr cluster; @@ -925,10 +933,6 @@ LIBCEPHSQLITE_API int sqlite3_cephsqlite_init(sqlite3* db, char** err, const sql } } - if (int rc = std::atexit(cephsqlite_atexit); rc) { - return SQLITE_INTERNAL; - } - if (int rc = sqlite3_auto_extension((void(*)(void))autoreg); rc) { return rc; } -- 2.47.3