]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/dbstore: fix memory leaks in unittest_dbstore_tests 66852/head
authorKefu Chai <k.chai@proxmox.com>
Fri, 9 Jan 2026 04:40:39 +0000 (12:40 +0800)
committerKefu Chai <k.chai@proxmox.com>
Fri, 9 Jan 2026 05:20:29 +0000 (13:20 +0800)
Fix memory leaks detected by AddressSanitizer in unittest_dbstore_tests.
The test was failing with ASan enabled due to SQLObjectOp objects not
being properly cleaned up.

ASan reported the following leaks:

  Direct leak of 200 byte(s) in 1 object(s) allocated from:
    #0 operator new(unsigned long)
    #1 SQLGetBucket::Execute(DoutPrefixProvider const*, rgw::store::DBOpParams*)
       /src/rgw/driver/dbstore/sqlite/sqliteDB.cc:1689
    #2 rgw::store::DB::ProcessOp(DoutPrefixProvider const*, ...)
       /src/rgw/driver/dbstore/common/dbstore.cc:258

  Direct leak of 200 byte(s) in 1 object(s) allocated from:
    #0 operator new(unsigned long)
    #1 SQLInsertBucket::Execute(DoutPrefixProvider const*, rgw::store::DBOpParams*)
       /src/rgw/driver/dbstore/sqlite/sqliteDB.cc:1433
    #2 rgw::store::DB::ProcessOp(DoutPrefixProvider const*, ...)
       /src/rgw/driver/dbstore/common/dbstore.cc:258

  SUMMARY: AddressSanitizer: 460550 byte(s) leaked in 1823 allocation(s).

Root cause: The DB::Destroy() method had an early return when the db
pointer was NULL, preventing cleanup of the objectmap which stores
SQLObjectOp pointers. These objects were allocated during test execution
but never freed.

Changes:
- Modified DB::Destroy() to always clean up objectmap even when db is NULL
- Added explicit delete in objectmapDelete() for consistency
- Added lsan suppression for SQLite internal allocations (indirect leaks)

After the fix, all direct leaks are eliminated. Only indirect leaks from
SQLite's internal memory management remain, which are now suppressed.

Test results:
- Before: 460,550 bytes leaked (including 2 direct leaks of 200 bytes each)
- After: 0 direct leaks, unittest_dbstore_tests passes with ASan

Signed-off-by: Kefu Chai <k.chai@proxmox.com>
qa/lsan.supp
src/rgw/driver/dbstore/common/dbstore.cc

index 055a703b0fcb5c46ddcc443dc8caf84987fb7f84..9418cc5de214474619b30023fbd453202fb1c9c7 100644 (file)
@@ -34,3 +34,7 @@ leak:^PyModule_ExecDef
 # following suppression mirrors qa/valgrind.supp
 # ignore ec plugin factory (FIXME SOMEDAY)
 leak:^ceph::ErasureCodePluginRegistry::load
+
+# SQLite internal allocations
+# These are indirect leaks from SQLite's internal memory management
+leak:libsqlite3.so
index 4d55ee97c572493e8a3c8f31f5f3b34f083eeb26..6db081ca3043d75929ba85a1205b0793bbeb1d70 100644 (file)
@@ -75,12 +75,10 @@ int DB::stopGC() {
 
 int DB::Destroy(const DoutPrefixProvider *dpp)
 {
-  if (!db)
-    return 0;
-
-  stopGC();
-
-  closeDB(dpp);
+  if (db) {
+    stopGC();
+    closeDB(dpp);
+  }
 
   {
     const std::lock_guard lk(mtx);
@@ -219,6 +217,8 @@ int DB::objectmapDelete(const DoutPrefixProvider *dpp, string bucket)
     return 0;
   }
 
+  // Delete the ObjectOp object to prevent memory leak
+  delete iter->second;
   DB::objectmap.erase(iter);
 
   return 0;