From 7985b282cac8b9177130e4a7997c68c6d158577e Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Sat, 26 Jun 2021 11:26:41 -0700 Subject: [PATCH] libcephsqlite: register atexit handler for cleanup We need to tear down the ceph vfs when sqlite3 (or other binaries) call exit(). Otherwise global state gets destructed which can cause library threads to segfault or raise exceptions. Also pull vfs struct out of appdata. We need to be able to detect double calls to the atexit handler which, sadly, can happen. Fixes: https://tracker.ceph.com/issues/50503 Fixes: https://tracker.ceph.com/issues/51372 Signed-off-by: Patrick Donnelly --- src/libcephsqlite.cc | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/libcephsqlite.cc b/src/libcephsqlite.cc index ccc4316b8fb..346cd3f1bc4 100644 --- a/src/libcephsqlite.cc +++ b/src/libcephsqlite.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -137,7 +138,6 @@ struct cephsqlite_appdata { std::unique_ptr logger; std::shared_ptr striper_logger; librados::Rados cluster; - struct sqlite3_vfs vfs{}; }; struct cephsqlite_fileloc { @@ -790,14 +790,25 @@ static int autoreg(sqlite3* db, char** err, const struct sqlite3_api_routines* t return SQLITE_OK; } +static void cephsqlite_atexit() +{ + if (auto vfs = sqlite3_vfs_find("ceph"); vfs) { + if (vfs->pAppData) { + auto&& appd = getdata(vfs); + delete &appd; + vfs->pAppData = nullptr; + } + } +} + LIBCEPHSQLITE_API int sqlite3_cephsqlite_init(sqlite3* db, char** err, const sqlite3_api_routines* api) { SQLITE_EXTENSION_INIT2(api); auto vfs = sqlite3_vfs_find("ceph"); if (!vfs) { + vfs = (sqlite3_vfs*) calloc(1, sizeof(sqlite3_vfs)); auto appd = new cephsqlite_appdata; - vfs = &appd->vfs; vfs->iVersion = 2; vfs->szOsFile = sizeof(struct cephsqlite_file); vfs->mxPathname = 4096; @@ -808,8 +819,15 @@ LIBCEPHSQLITE_API int sqlite3_cephsqlite_init(sqlite3* db, char** err, const sql vfs->xAccess = Access; vfs->xFullPathname = FullPathname; vfs->xCurrentTimeInt64 = CurrentTime; - appd->cct = nullptr; - sqlite3_vfs_register(vfs, 0); + if (int rc = sqlite3_vfs_register(vfs, 0); rc) { + delete appd; + free(vfs); + return rc; + } + } + + if (int rc = std::atexit(cephsqlite_atexit); rc) { + return SQLITE_INTERNAL; } if (int rc = sqlite3_auto_extension((void(*)(void))autoreg); rc) { -- 2.39.5