wallet: use Mutex for g_sqlite_mutex instead of GlobalMutex #25491

pull vasild wants to merge 1 commits into bitcoin:master from vasild:g_sqlite_mutex changing 2 files +16 −4
  1. vasild commented at 3:55 PM on June 28, 2022: contributor

    Using Mutex provides stronger guarantee than GlobalMutex wrt Clang's thread safety analysis. Thus it is better to reduce the usage of GlobalMutex in favor of Mutex.

    Using Mutex for g_sqlite_mutex is ok because its usage is limited in wallet/sqlite.cpp and it does not require propagating the negative annotations to not relevant code.

  2. fanquake added the label Wallet on Jun 28, 2022
  3. fanquake requested review from ajtowns on Jun 28, 2022
  4. w0xlt approved
  5. DrahtBot commented at 12:03 PM on June 29, 2022: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK hebasto, TheCharlatan, achow101
    Stale ACK w0xlt

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

  6. maflcko commented at 1:36 PM on June 29, 2022: member

    I tried to see if this made any difference in practice, but it didn't. Annotations are disabled for con-/de-structors:

    diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp
    index 5d81af2fbf..c8a9262150 100644
    --- a/src/wallet/sqlite.cpp
    +++ b/src/wallet/sqlite.cpp
    @@ -113,7 +113,6 @@ SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_pa
             if (ret != SQLITE_OK) {
                 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret)));
             }
    -    }
     
         try {
             Open();
    @@ -122,6 +121,7 @@ SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_pa
             Cleanup();
             throw;
         }
    +    }
     }
     
     void SQLiteBatch::SetupSQLStatements()
    

    Also, it is annotated in the implementation only (not the definition), (for obvious reasons, though).

    However, it does add a hint for developer reading the code, so lgtm.

  7. in src/wallet/sqlite.cpp:29 in 83074b1165 outdated
      22 | @@ -23,7 +23,13 @@
      23 |  namespace wallet {
      24 |  static constexpr int32_t WALLET_SCHEMA_VERSION = 0;
      25 |  
      26 | -static GlobalMutex g_sqlite_mutex;
      27 | +/**
      28 | + * This mutex protects SQLite initialization and shutdown.
      29 | + * sqlite3_config() and sqlite3_shutdown() are not threadsafe (sqlite3_initialize() is).
      30 | + * Concurrent threads that execute SQLiteDatabase::SQLiteDatabase() should have just one
    


    furszy commented at 1:45 PM on June 29, 2022:

    I'm not sure what you meant with this sentence. g_sqlite_count can be higher than one.


    maflcko commented at 2:01 PM on June 29, 2022:

    "one" refers to "concurrent threads"


    vasild commented at 3:27 PM on July 12, 2022:

    Changed "one" to "one of them".

  8. maflcko removed the label Wallet on Jul 4, 2022
  9. DrahtBot added the label Wallet on Jul 4, 2022
  10. in src/wallet/sqlite.cpp:153 in 83074b1165 outdated
     149 | @@ -144,7 +150,7 @@ SQLiteDatabase::~SQLiteDatabase()
     150 |      Cleanup();
     151 |  }
     152 |  
     153 | -void SQLiteDatabase::Cleanup() noexcept
     154 | +void SQLiteDatabase::Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex)
    


    ajtowns commented at 12:53 AM on July 12, 2022:

    from developer-notes: "In functions that are declared separately from where they are defined, the thread safety annotations should be added exclusively to the function declaration."

    Could move g_sqlite_mutex and g_sqlite_count to be static members of SQLiteDatabase` though I think.


    vasild commented at 3:23 PM on July 12, 2022:

    Moved to SQLiteDatabase. This way if some other method calls Cleanup() from the .h file they will be enforced to not hold the mutex. This is impossible though, because the mutex was defined solely in the .cpp file. I think either way is fine.

    Unrelated, the developer-notes read:

    ... should be added exclusively to the function declaration. Annotations on the definition could lead to false positives (lack of compile failure) at call sites between the two.

    Should that not be "false negatives"?

    • false positive: it incorrectly indicates that I am holding the mutex when I am not holding it
    • false negative: it incorrectly indicates that I am not holding the mutex when I am holding it

    What is "the two"?

  11. vasild force-pushed on Jul 12, 2022
  12. vasild commented at 3:14 PM on July 12, 2022: contributor

    83074b1165...0be7de52f2: put the mutex and the variable as a static members of SQLiteDatabase, as suggested

  13. achow101 commented at 7:39 PM on October 12, 2022: member
  14. vasild commented at 9:32 AM on October 13, 2022: contributor

    cc @w0xlt (ACKed a previous version of this)

  15. in src/wallet/sqlite.h:76 in 0be7de52f2 outdated
      72 | +     * of them do the init and the rest wait for it to complete before all can proceed.
      73 | +     */
      74 | +    static Mutex g_sqlite_mutex;
      75 | +    static int g_sqlite_count GUARDED_BY(g_sqlite_mutex);
      76 | +
      77 | +    void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex);
    


    hebasto commented at 9:02 PM on October 13, 2022:

    Not sure about this annotation as @MarcoFalke pointed:

    Annotations are disabled for con-/de-structors

    Nevertheless, it would be nice to add AssertLockNotHeld(g_sqlite_mutex); to the function implemetation.


    vasild commented at 12:39 PM on October 14, 2022:

    Added AssertLockNotHeld().

    I kept the annotation on the Cleanup() method, even though it is called only from the constructor and the destructor in case it gets called from elsewhere in the future.

    This looks a bit strange:

    Mutex m1;
    int global_counter GUARDED_BY(m1){0};
    
    void f() EXCLUSIVE_LOCKS_REQUIRED(!m1)
    {
        AssertLockNotHeld(m1);
        LOCK(m1);
        ++global_counter;
    }
    
    SQLiteDatabase::SQLiteDatabase()
    {
        LOCK(m1);
        // ok!?
        f();
    
    void SQLiteDatabase::Open() // any other method
    {
        LOCK(m1);
        // error: cannot call function 'f' while mutex 'm1' is held [-Werror,-Wthread-safety-analysis]
        f();
    

    I understand annotations on the constructor are disabled, but the above is more than that. Are constructors treated like NO_THREAD_SAFETY_ANALYSIS?


    ajtowns commented at 3:56 PM on October 18, 2022:

    Are constructors treated like NO_THREAD_SAFETY_ANALYSIS?

    Yes, see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#no-checking-inside-constructors-and-destructors

  16. hebasto commented at 9:09 PM on October 13, 2022: member

    Approach ACK 0be7de52f2d0d7c101afdf1b4e315a395015867b.

    Built on Ubuntu 22.04 using clang 14.0 with -Wthread-safety-negative.

  17. wallet: use Mutex for g_sqlite_mutex instead of GlobalMutex
    Using `Mutex` provides stronger guarantee than `GlobalMutex` wrt Clang's
    thread safety analysis. Thus it is better to reduce the usage of
    `GlobalMutex` in favor of `Mutex`.
    
    Using `Mutex` for `g_sqlite_mutex` is ok because its usage is limited in
    `wallet/sqlite.cpp` and it does not require propagating the negative
    annotations to not relevant code.
    4163093d63
  18. vasild force-pushed on Oct 14, 2022
  19. vasild commented at 12:37 PM on October 14, 2022: contributor

    0be7de52f2...4163093d63: rebase and add AssertLockNotHeld() as suggested

  20. hebasto approved
  21. hebasto commented at 8:37 AM on October 15, 2022: member

    re-ACK 4163093d6374e865dc57e33dbea0e7e359062e0a

  22. TheCharlatan approved
  23. TheCharlatan commented at 9:36 AM on March 6, 2023: contributor

    ACK 4163093d6374e865dc57e33dbea0e7e359062e0a

  24. achow101 commented at 3:42 PM on March 6, 2023: member

    ACK 4163093d6374e865dc57e33dbea0e7e359062e0a

  25. DrahtBot requested review from w0xlt on Mar 6, 2023
  26. achow101 merged this on Mar 6, 2023
  27. achow101 closed this on Mar 6, 2023

  28. vasild deleted the branch on Mar 6, 2023
  29. sidhujag referenced this in commit d7020f128c on Mar 6, 2023
  30. bitcoin locked this on Mar 5, 2024

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-21 15:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me