SQLite journal/concurrency issues: SqliteStorage::getBufferInfo(): received more then one Buffer!
Every few days, my core crashes with an error like:
2019-01-30 11:19:09 [Error] SqliteStorage::getBufferInfo(): received more then one Buffer! 2019-01-30 11:19:09 [Error] Query: "SELECT bufferid, buffertype, groupid\nFROM buffer\nWHERE buffer.networkid = :networkid AND buffer.user id = :userid AND buffer.buffercname = :buffercname" 2019-01-30 11:19:09 [Error] bound Values: 2019-01-30 11:19:09 [Error] 0 : cynede_afk 2019-01-30 11:19:09 [Error] 1 : 1 2019-01-30 11:19:09 [Error] 2 : 1 2019-01-30 11:19:09 [FATAL] ASSERT: "false" in file /home/mgorny/git/quassel/src/core/sqlitestorage.cpp, line 1176
I have no clue why this would happen. Is it possible that the database was corrupted as a result of earlier crashes?
Can we have some nicer behavior here? Is there a nice way to fix the database by hand?
Finally, can we enforce this via database constraints?
#1 Updated by digitalcircuit 15 days ago
- Subject changed from [Error] SqliteStorage::getBufferInfo(): received more then one Buffer! to SQLite journal/concurrency issues: SqliteStorage::getBufferInfo(): received more then one Buffer!
- Category set to Quassel Core
I agree that this should be enforced by database constraints, that Quassel should handle this more gracefully, and I'm not sure how Quassel would get into this state.
My guess is Quassel crashed in the middle of a write before it completed, or Quassel's current locking mechanism in SQLite allowed concurrent writes. Based on the bound values, it seems like a private message buffer was renamed (either due to
/nick changes, or manual action). To fix this and other issues, Quassel likely needs to adopt SQLite's WAL mode , which had performance issues with older SQLite versions (e.g. as in Ubuntu 14.04). With 0.14/
master increasing build requirements, this is something we can finally try to tackle.
Crashes once this inconsistency exists are likely merely periodic as it'd only occur when Quassel tries to get this buffer information, which may be when a particular user logs in, etc.
To recover, you should be able to find the duplicate buffer and rename it:
1. Find the IDs of the duplicate buffers, the ones with the same name/user ID/network ID¶
With the original query of…
SELECT bufferid, buffertype, groupid FROM buffer WHERE buffer.networkid = :networkid AND buffer.userid = :userid AND buffer.buffercname = :buffercname;
…and the bound values of…
This should be…
SELECT bufferid FROM buffer WHERE buffer.networkid = 1 AND buffer.userid = 1 AND buffer.buffercname = 'cynede_afk';
2. Rename one of the buffers to avoid the collision¶
Make a backup first! I'm not 100% certain this will fix the issue.
buffername of the problematic buffer to a unique name…
UPDATE buffer SET buffercname = 'cynede_afk_dup', buffername = 'cynede_afk_dup' WHERE bufferid = XXXX; -- Replace XXXX with one of the buffer ID numbers from above
Retry the query in step 1. If there's still more results, repeat this, but pick different names for
Thank you. I've just applied the recovery and we'll see what happens now. It turned out that `cynede_afk` had two duplicates with very different numbers (one 1xx, other 4xx), so I suspect this might have been going for some time already. Though I suspect I never knew because I haven't been running debug builds before.
#3 Updated by digitalcircuit 8 days ago
Thanks for feedback; I'm glad the recovery worked! That does seem odd, and given the
assert() only on debug builds, it's a relief it's likely not a new issue/regression.
Quassel should still handle this better, as originally agreed.
Pardon my delayed reply; turns out I need to manually watch an issue after commenting in order to get email notifications.