symisc / unqlite

An Embedded NoSQL, Transactional Database Engine
https://unqlite.symisc.net
Other
2.11k stars 164 forks source link

Segfault & Busy Loop When Sharing Database Between Processes #168

Open VaslD opened 6 months ago

VaslD commented 6 months ago

I was experimenting with sharing a single database between iOS app and app extensions, when I encountered an always reproducible crash. (It seems to reference https://github.com/symisc/unqlite/issues/135 but I haven't got time to dig deep.)

To easily reproduce it, I write a benchmark app that stores random key-values and fetches it back, then sleeps for about half a second, rinses and repeats for almost indefinitely. When I launch this tool twice (operating on the same database file), one process crashes.

https://github.com/symisc/unqlite/assets/3415065/d8028cd9-b844-48e5-8a85-6ebcd9dbcf1e

The crash isn't deterministic (the first or the second to launch), contrary to what the video shows. (The video was cut short due to GitHub size limit.) But I can never have both survive long enough.

Also, after that one process crashes, it sends the other into an UNQLITE_BUSY (-14) loop, which I assume is caused by either unrelinquished UNIX lock or corrupted book-keeping, making the whole situation fatal unless I close and reopen the database file everywhere.

Screenshot 2024-04-23 15 12 40@2x

Further investigation shows that the file descriptor was somehow set to null on a valid database (unqlite *) and pager (Pager *).

Screenshot 2024-04-23 15 36 34@2x


unqlite 1.1.9 compiled with -DUNQLITE_ENABLE_THREADS, on macOS 14.4 and iOS 17.0