SQLite Forum

Timeline
Login

3 forum posts by user timwoj

2021-08-09
20:15 Reply: ThreadSantizer warning for sqlite3_enable_shared_cache() (artifact: 60e14e51ae user: timwoj)

So is this something that can be fixed on the SQLite side? I can disable the call if I'm under ThreadSanitizer, but I'd rather not if it can just be fixed.

2021-06-28
20:57 Edit: ThreadSantizer warning for sqlite3_enable_shared_cache() (artifact: 5830036e09 user: timwoj)

I'm running into a warning from ThreadSanitizer while using sqlite3_enable_shared_cache() between two threads. I've minimized it down to a simple test program below, followed by the back trace from TSan.

#include <chrono>
#include <thread>
#include <sqlite3.h>

namespace {

void Init() {
	sqlite3_enable_shared_cache(1);
	std::this_thread::sleep_for(std::chrono::seconds(2));
}

}  // namespace

int main(int argc, char* argv[]) {
	std::thread t1(&Init);
	std::thread t2(&Init);
	t1.join();
	t2.join();

	return 0;
}

With that file in test.cc and sqlite3.{h,c} in the same directory, I'm building with:

clang-11 -fsanitize=thread -g -c sqlite3.c
clang-11 -std=c++17 -stdlib=libstdc++ -fsanitize=thread -g -I. -c test.cc
clang-11 -lstdc++ -std=c++17 -fsanitize=thread *.o -o warn_test

Running warn_test results in this report from TSan:

==================
WARNING: ThreadSanitizer: data race (pid=123110)
  Write of size 4 at 0x000000706dac by thread T2:
    #0 sqlite3_enable_shared_cache /home/tim/test/sqlite3.c:65571:3 (race+0x4c3d8a)
    #1 (anonymous namespace)::Init() /home/tim/test/test.cc:12:2 (race+0x6a35ea)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:60:14 (race+0x6a49ed)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:95:14 (race+0x6a48f0)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:244:13 (race+0x6a4898)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:251:11 (race+0x6a4838)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:195:13 (race+0x6a461f)
    #7 <null> <null> (libstdc++.so.6+0xd6de3)

  Previous write of size 4 at 0x000000706dac by thread T1:
    #0 sqlite3_enable_shared_cache /home/tim/test/sqlite3.c:65571:3 (race+0x4c3d8a)
    #1 (anonymous namespace)::Init() /home/tim/test/test.cc:12:2 (race+0x6a35ea)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:60:14 (race+0x6a49ed)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:95:14 (race+0x6a48f0)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:244:13 (race+0x6a4898)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:251:11 (race+0x6a4838)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:195:13 (race+0x6a461f)
    #7 <null> <null> (libstdc++.so.6+0xd6de3)

  Location is global 'sqlite3Config' of size 424 at 0x000000706c60 (race+0x000000706dac)

  Thread T2 (tid=123113, running) created by main thread at:
    #0 pthread_create <null> (race+0x425ccb)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xd70a8)
    #2 main /home/tim/test/test.cc:20:14 (race+0x6a34d1)

  Thread T1 (tid=123112, running) created by main thread at:
    #0 pthread_create <null> (race+0x425ccb)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xd70a8)
    #2 main /home/tim/test/test.cc:19:14 (race+0x6a34a7)

SUMMARY: ThreadSanitizer: data race /home/tim/test/sqlite3.c:65571:3 in sqlite3_enable_shared_cache
==================
ThreadSanitizer: reported 1 warnings

I'm able to fix it by changing sqlite3GlobalConfig.sharedCacheEnabled to be an atomic_int and #include'ing <stdatomic.h> but I understand that's a C11 feature and may not be acceptable. I did try to fix it using AtomicLoad() and AtomicStore() but for some reason I was getting the same warning from TSan.

19:56 Post: ThreadSantizer warning for sqlite3_enable_shared_cache() (artifact: 54424d80ee user: timwoj)

I'm running into a warning from ThreadSanitizer while using sqlite3_enable_shared_cache() between two threads. I've minimized it down to a simple test program below, followed by the back trace from TSan.

#include <chrono>
#include <thread>
#include <sqlite3.h>

namespace {

void Init() {
	sqlite3_enable_shared_cache(1);
	std::this_thread::sleep_for(std::chrono::seconds(2));
}

}  // namespace

int main(int argc, char* argv[]) {
	std::thread t1(&Init);
	std::thread t2(&Init);
	t1.join();
	t2.join();

	return 0;
}

With that file in test.cc and sqlite3.{h,c} in the same directory, I'm building with:

clang-11 -fsanitize=thread -g -c sqlite3.c
clang-11 -std=c++17 -stdlib=libstdc++ -fsanitize=thread -g -I. -c test.cc
clang -lstdc++ -std=c++17 -fsanitize=thread *.o -o warn_test

Running warn_test results in this report from TSan:

==================
WARNING: ThreadSanitizer: data race (pid=123110)
  Write of size 4 at 0x000000706dac by thread T2:
    #0 sqlite3_enable_shared_cache /home/tim/test/sqlite3.c:65571:3 (race+0x4c3d8a)
    #1 (anonymous namespace)::Init() /home/tim/test/test.cc:12:2 (race+0x6a35ea)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:60:14 (race+0x6a49ed)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:95:14 (race+0x6a48f0)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:244:13 (race+0x6a4898)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:251:11 (race+0x6a4838)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:195:13 (race+0x6a461f)
    #7 <null> <null> (libstdc++.so.6+0xd6de3)

  Previous write of size 4 at 0x000000706dac by thread T1:
    #0 sqlite3_enable_shared_cache /home/tim/test/sqlite3.c:65571:3 (race+0x4c3d8a)
    #1 (anonymous namespace)::Init() /home/tim/test/test.cc:12:2 (race+0x6a35ea)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:60:14 (race+0x6a49ed)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/invoke.h:95:14 (race+0x6a48f0)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:244:13 (race+0x6a4898)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:251:11 (race+0x6a4838)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/thread:195:13 (race+0x6a461f)
    #7 <null> <null> (libstdc++.so.6+0xd6de3)

  Location is global 'sqlite3Config' of size 424 at 0x000000706c60 (race+0x000000706dac)

  Thread T2 (tid=123113, running) created by main thread at:
    #0 pthread_create <null> (race+0x425ccb)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xd70a8)
    #2 main /home/tim/test/test.cc:20:14 (race+0x6a34d1)

  Thread T1 (tid=123112, running) created by main thread at:
    #0 pthread_create <null> (race+0x425ccb)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xd70a8)
    #2 main /home/tim/test/test.cc:19:14 (race+0x6a34a7)

SUMMARY: ThreadSanitizer: data race /home/tim/test/sqlite3.c:65571:3 in sqlite3_enable_shared_cache
==================
ThreadSanitizer: reported 1 warnings

I'm able to fix it by changing sqlite3GlobalConfig.sharedCacheEnabled to be an atomic_int and #include'ing <stdatomic.h> but I understand that's a C11 feature and may not be acceptable. I did try to fix it using AtomicLoad() and AtomicStore() but for some reason I was getting the same warning from TSan.