From be86f191e726d2e1690087d4b808c6d18c92729a Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Tue, 29 Jun 2021 08:01:56 -0700 Subject: [PATCH] cephsqlite: add comment on atexit Signed-off-by: Patrick Donnelly --- src/libcephsqlite.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/libcephsqlite.cc b/src/libcephsqlite.cc index 346cd3f1bc4df..25782ff93974f 100644 --- a/src/libcephsqlite.cc +++ b/src/libcephsqlite.cc @@ -790,6 +790,30 @@ static int autoreg(sqlite3* db, char** err, const struct sqlite3_api_routines* t return SQLITE_OK; } +/* You may wonder why we have an atexit handler? After all, atexit/exit creates + * a mess for multithreaded programs. Well, sqlite3 does not have an API for + * orderly removal of extensions. And, in fact, any API we might make + * unofficially (such as "sqlite3_cephsqlite_fini") would potentially race with + * other threads interacting with sqlite3 + the "ceph" VFS. There is a method + * for removing a VFS but it's not called by sqlite3 in any error scenario and + * there is no mechanism within sqlite3 to tell a VFS to unregister itself. + * + * This all would be mostly okay if /bin/sqlite3 did not call exit(3), but it + * does. (This occurs only for the sqlite3 binary, not when used as a library.) + * exit(3) calls destructors on all static-duration structures for the program. + * This breaks any outstanding threads created by the librados handle in all + * sorts of fantastic ways from C++ exceptions to memory faults. In general, + * Ceph libraries are not tolerant of exit(3) (_exit(3) is okay!). Applications + * must clean up after themselves or _exit(3). + * + * So, we have an atexit handler for libcephsqlite. This simply shuts down the + * RADOS handle. We can be assured that this occurs before any ceph library + * static-duration structures are destructed due to ordering guarantees by + * exit(3). Generally, we only see this called when the VFS is used by + * /bin/sqlite3 and only during sqlite3 error scenarios (like I/O errors + * arrising from blocklisting). + */ + static void cephsqlite_atexit() { if (auto vfs = sqlite3_vfs_find("ceph"); vfs) { -- 2.39.5