Commit ff6cdf57 authored by Ahmad Samir's avatar Ahmad Samir
Browse files

Fix crash by handling exceptions thrown by GlassTable::set_overwritten

Xapian::Enquire::get_mset ultimately calls GlassTable::block_to_cursor,
which could throw Xapian::DatabaseModifiedError if the database has been
modified/deviated too much since it was opened for searching; handle that
case by trying to call reopen on the database (as per the upstream error
message[1]), then query it again, if that fails just return.

Also handle one other exception, Xapian::DatabaseCorruptError; this has
been reported in [2].

Use QByteArray::toStdString when calling the Xapian::Database ctor.

[1] https://xapian.org/docs/sourcedoc/html/glass__table_8cc_source.html#l00288
[2] https://bugs.kde.org/show_bug.cgi?id=363928#c9

BUG: 401865
CCBUG: 363928
parent 1440ec18
Pipeline #31063 passed with stage
in 23 minutes and 8 seconds
......@@ -136,7 +136,7 @@ void IndexedItemsPrivate::findIndexedInDatabase(QSet<Akonadi::Item::Id> &indexed
{
Xapian::Database db;
try {
db = Xapian::Database(QFile::encodeName(dbPath).constData());
db = Xapian::Database(QFile::encodeName(dbPath).toStdString());
} catch (const Xapian::DatabaseError &e) {
qCCritical(AKONADI_SEARCH_PIM_LOG) << "Failed to open database" << dbPath << ":" << QString::fromStdString(e.get_msg());
return;
......@@ -146,10 +146,29 @@ void IndexedItemsPrivate::findIndexedInDatabase(QSet<Akonadi::Item::Id> &indexed
Xapian::Enquire enquire(db);
enquire.set_query(query);
Xapian::MSet mset = enquire.get_mset(0, UINT_MAX);
Xapian::MSetIterator it = mset.begin();
for (; it != mset.end(); it++) {
indexed << *it;
auto getResults = [&enquire, &indexed]() {
Xapian::MSet mset;
mset = enquire.get_mset(0, UINT_MAX);
Xapian::MSetIterator it = mset.begin();
for (auto result : mset) {
indexed << result;
}
};
try {
getResults();
} catch (const Xapian::DatabaseModifiedError &e) {
qCCritical(AKONADI_SEARCH_PIM_LOG) << "Failed to read database" << dbPath << ":" << QString::fromStdString(e.get_msg());
qCCritical(AKONADI_SEARCH_PIM_LOG) << "Calling reopen() on database" << dbPath << "and trying again";
if (db.reopen()) { // only try again once
try {
getResults();
} catch (const Xapian::DatabaseModifiedError &e) {
qCCritical(AKONADI_SEARCH_PIM_LOG) << "Failed to query database" << dbPath << "even after calling reopen()";
}
}
} catch (const Xapian::DatabaseCorruptError &e) {
qCCritical(AKONADI_SEARCH_PIM_LOG) << "Failed to query database" << dbPath << ":" << QString::fromStdString(e.get_msg());
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment