]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
libcephsqlite: ensure atexit handlers are registered after openssl 68125/head
authorPatrick Donnelly <pdonnell@ibm.com>
Tue, 7 Apr 2026 20:43:56 +0000 (16:43 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Tue, 7 Apr 2026 20:44:39 +0000 (16:44 -0400)
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 <pdonnell@ibm.com>
src/libcephsqlite.cc

index c386271b4e8989a34a6b5a1e6ab226ce60139f69..afafe6a0d7b65f179ff64f0689c212b2dcc27bed 100644 (file)
@@ -90,6 +90,8 @@ enum {
 using cctptr = boost::intrusive_ptr<CephContext>;
 using rsptr = std::shared_ptr<librados::Rados>;
 
+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;
   }