SQLite Forum

DATA RACE: Found in sqlite3.c
Login

DATA RACE: Found in sqlite3.c

(1) By Zu-Ming Jiang (jiang446079653) on 2020-04-29 01:59:57 [link] [source]

Dear SQLite developers:

I used my fuzz-testing tool, connzer, to detect data race in SQLite. Here is a data race found by connzer. I wish you can help me check whether it is a real race, thanks!!

The following is the race report.

Race report

Race object: pShmNode->pShmMutex

Thread 1:

Access: pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);

Line number: sqlite3.c, 37258

Call stack:

  1. unixOpenSharedMemory()
  2. unixShmMap()
  3. sqlite3OsShmMap()
  4. walIndexPageRealloc()
  5. walIndexPage()
  6. walIndexReadHdr()
  7. walTryBeginRead()
  8. sqlite3WalBeginReadTransaction()
  9. pagerBeginReadTransaction()
  10. sqlite3PagerSharedLock()
  11. lockBtree()
  12. sqlite3BtreeBeginTrans()
  13. sqlite3VdbeExec()
  14. sqlite3Step()
  15. sqlite3_step()
  16. sqlite3_exec()
  17. sql_script_x()
  18. walthread2_thread()
  19. launch_thread_main()

Lock:

  1. unixEnterMutex()

Thread 2:

Access: sqlite3_mutex_leave(pShmNode->pShmMutex);

Line number: sqlite3.c; 37308

Call stack:

  1. unixOpenSharedMemory()
  2. unixShmMap()
  3. sqlite3OsShmMap()
  4. walIndexPageRealloc()
  5. walIndexPage()
  6. walIndexReadHdr()
  7. walTryBeginRead()
  8. sqlite3WalBeginReadTransaction()
  9. pagerBeginReadTransaction()
  10. sqlite3PagerSharedLock()
  11. lockBtree()
  12. sqlite3BtreeBeginTrans()
  13. sqlite3BtreeSetVersion()
  14. sqlite3VdbeExec()
  15. sqlite3Step()
  16. sqlite3_step()
  17. sqlite3_exec()
  18. sql_script_x()
  19. walthread2_thread()
  20. launch_thread_main()

Lock:

  1. sqlite3_mutex_enter(pShmNode->pShmMutex)

My fuzzer finds that these 2 accesses can be executed concurrently, and they are protected by different locks, so my fuzzer report this race.

(2.1) By Clemens Ladisch (cladisch) on 2020-04-29 16:47:38 edited from 2.0 in reply to 1 [link] [source]

My fuzzer finds that these 2 accesses can be executed concurrently

The fuzzer is wrong. Have a look at the first assert() in lockBtree(), which checks the that sqlite3BtreeEnter() did lock correctly.

they are protected by different locks

Do you have any evidence for this assertion? A BtShared object has a single Pager, which has a single Wal, which has a single file, which has a single unixShmNode.

(3) By Warren Young (wyoung) on 2020-04-29 07:38:37 in reply to 2.0 [source]

The fuzzer is wrong. Have a look at the first assert() in lockBtree().

An assert only checks for things in debug mode. Things it does get compiled out of release binaries, so you can't count on what happens inside. I'm not saying this particular lock doesn't get acquired, but you should point somewhere up-stack to make your point, not at this line.

But second, the two data structures involved aren't even the same. OP is talking about a struct sqlite3_mutex, while you're pointing out a struct BtShared. Again, this doesn't mean you're wrong, just that your explanation is insufficient to the task.