Bug 493393

Summary: akonadi-db-migrator segfaults attempting to migrate to SQLite
Product: [Frameworks and Libraries] Akonadi Reporter: Andrew Hutchings <andrew>
Component: MigrationAssignee: kdepim bugs <pim-bugs-null>
Status: CONFIRMED ---    
Severity: crash CC: amessina, asturm, axel.braun, bernhardu, carl, colin.thomson, danielroschka, dilfridge, gik-kbugs, i, joshua, katze_942, kde, manz, marek.gresko, morguldir, sam, starodubcevmax, stephanolbrich
Priority: NOR    
Version First Reported In: unspecified   
Target Milestone: ---   
Platform: Fedora RPMs   
OS: Linux   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:

Description Andrew Hutchings 2024-09-20 05:57:40 UTC
SUMMARY
When attempting to migrate to SQLite in Fedora 40, akonadi-db-migrator segfaults.

STEPS TO REPRODUCE
1. akonadi-db-migrator --newengine sqlite

OBSERVED RESULT
org.kde.pim.akonadiserver: mysqld for Akonadi is already running, trying to connect to it.
akonadi.collectionattributetable                   OK
akonadi.collectionmimetyperelation                 OK
akonadi.collectionpimitemrelation                  OK
akonadi.collectiontable                            OK
akonadi.flagtable                                  OK
akonadi.mimetypetable                              OK
akonadi.parttable                                  OK
akonadi.parttypetable                              OK
akonadi.pimitemflagrelation                        OK
akonadi.pimitemtable                               OK
akonadi.pimitemtagrelation                         OK
akonadi.relationtable                              OK
akonadi.relationtypetable                          OK
akonadi.resourcetable                              OK
akonadi.schemaversiontable                         OK
akonadi.tagattributetable                          OK
akonadi.tagremoteidresourcerelationtable           OK
akonadi.tagtable                                   OK
akonadi.tagtypetable                               OK
This installation of MariaDB is already upgraded to 10.11.6-MariaDB.
There is no need to run mysql_upgrade again for 10.11.8-MariaDB.
You can use --force if you still want to run mysql_upgrade
org.kde.pim.akonadiserver: Running DB initializer
org.kde.pim.akonadiserver: DB initializer done
org.kde.pim.akonadiserver: Running DB initializer
[1]    233034 segmentation fault (core dumped)  akonadi-db-migrator --newengine sqlite


SOFTWARE/OS VERSIONS
(available in the Info Center app, or by running `kinfo` in a terminal window)
Linux/KDE Plasma: Fedora 40
KDE Plasma Version: 6.1.4
KDE Frameworks Version: 6.5.0
Qt Version: 6.7.2

ADDITIONAL INFORMATION

GDB info:

Akonadi::Server::DbInitializer::run (this=0x7fffe003a900) at /usr/src/debug/akonadi-server-24.08.0-1.fc40.x86_64/src/server/storage/dbinitializer.cpp:82                                
82              SchemaVersion version = SchemaVersion::retrieveAll(store).at(0);
(gdb) bt
#0  Akonadi::Server::DbInitializer::run (this=0x7fffe003a900) at /usr/src/debug/akonadi-server-24.08.0-1.fc40.x86_64/src/server/storage/dbinitializer.cpp:82
#1  0x00005555555bd7ba in Akonadi::Server::DataStore::init (this=0x7fffe0045190) at /usr/include/qt6/QtCore/qsharedpointer_impl.h:274
#2  0x00005555555a712a in (anonymous namespace)::prepareDatabase (config=config@entry=0x7fffe00089d0)
    at /usr/src/debug/akonadi-server-24.08.0-1.fc40.x86_64/src/server/dbmigrator/dbmigrator.cpp:194
#3  0x00005555555ac340 in Akonadi::Server::DbMigrator::runMigrationThread (this=0x7fffffffd7a0)
    at /usr/src/debug/akonadi-server-24.08.0-1.fc40.x86_64/src/server/dbmigrator/dbmigrator.cpp:533
#4  operator() (__closure=0x5555557523a8) at /usr/src/debug/akonadi-server-24.08.0-1.fc40.x86_64/src/server/dbmigrator/dbmigrator.cpp:452
#5  0x00005555555ae95d in std::__invoke_impl<void, Akonadi::Server::DbMigrator::startMigration()::<lambda()> > (__f=<optimized out>) at /usr/include/c++/14/bits/invoke.h:61
#6  std::__invoke<Akonadi::Server::DbMigrator::startMigration()::<lambda()> > (__fn=<optimized out>) at /usr/include/c++/14/bits/invoke.h:96
#7  std::invoke<Akonadi::Server::DbMigrator::startMigration()::<lambda()> > (__fn=<optimized out>) at /usr/include/c++/14/functional:120
#8  operator()<> (__closure=<optimized out>) at /usr/include/qt6/QtCore/qthread.h:125
#9  std::__invoke_impl<void, QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > (__f=<optimized out>) at /usr/include/c++/14/bits/invoke.h:61
#10 std::__invoke<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> >
    (__fn=<optimized out>) at /usr/include/c++/14/bits/invoke.h:96
#11 std::thread::_Invoker<std::tuple<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > >::_M_invoke<0> (this=<optimized out>) at /usr/include/c++/14/bits/std_thread.h:301
#12 std::thread::_Invoker<std::tuple<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > >::operator() (this=<optimized out>) at /usr/include/c++/14/bits/std_thread.h:308
#13 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > >, void>::operator()
    (this=0x7fffe57ffa60) at /usr/include/c++/14/future:1439
#14 std::__invoke_impl<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > >, void>&> (__f=...) at /usr/include/c++/14/bits/invoke.h:61
#15 std::__invoke_r<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > >, void>&> (__fn=...) at /usr/include/c++/14/bits/invoke.h:114
#16 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>(), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > >, void> >::_M_invoke(const std::_Any_data &) (__functor=...)
    at /usr/include/c++/14/bits/std_function.h:291
#17 0x00005555555a49b6 in std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()>::operator() (this=<optimized out>)
    at /usr/include/c++/14/bits/std_function.h:591
#18 std::__future_base::_State_baseV2::_M_do_set (this=0x555555752380, __f=<optimized out>, __did_set=0x7fffe57ffa17) at /usr/include/c++/14/future:596
#19 0x00007ffff6caba4b in __pthread_once_slow (once_control=0x555555752398, init_routine=0x7ffff6ee5f60 <std::__once_proxy()>) at pthread_once.c:116
#20 0x00007ffff6cabab9 in ___pthread_once (once_control=<optimized out>, init_routine=<optimized out>) at pthread_once.c:143
#21 0x00005555555aeb38 in __gthread_once (__once=0x555555752398, __func=<optimized out>) at /usr/include/c++/14/x86_64-redhat-linux/bits/gthr-default.h:713
#22 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()>*, bool*>
    (__once=..., __f=@0x7fffe57ffa30: (void (std::__future_base::_State_baseV2::*)(std::__future_base::_State_baseV2 * const, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()> *, bool *)) 0x5555555a4980 <std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*)>) at /usr/include/c++/14/mutex:916
#23 std::__future_base::_State_baseV2::_M_set_result (this=0x555555752380, __res=..., __ignore_failure=true) at /usr/include/c++/14/future:435
#24 std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:53&& ...)> > >, void>::_M_complete_async(void) (this=0x555555752380) at /usr/include/c++/14/future:1712
#25 0x00007ffff74b8417 in std::__future_base::_State_baseV2::wait (this=0x555555752380) at /usr/include/c++/14/future:357
#26 std::__basic_future<void>::_M_get_result (this=0x5555557523f0) at /usr/include/c++/14/future:748
#27 std::future<void>::get (this=0x5555557523f0) at /usr/include/c++/14/future:920
#28 QThreadCreateThread::run (this=0x5555557523e0) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/thread/qthread.cpp:1234
#29 0x00007ffff755473c in operator() (__closure=<optimized out>) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/thread/qthread_unix.cpp:326
#30 (anonymous namespace)::terminate_on_exception<QThreadPrivate::start(void*)::<lambda()> > (t=<optimized out>)
    at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/thread/qthread_unix.cpp:262
#31 QThreadPrivate::start (arg=0x5555557523e0) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/thread/qthread_unix.cpp:285
#32 0x00007ffff6ca66d7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#33 0x00007ffff6d2a60c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78
Comment 1 Maxim Starodubcev 2025-02-06 12:20:47 UTC
I have the same BUG on ArchLinux
Linux 6.13.1-arch1-1
akonadi-db-migrator 6.3.1 (24.12.1)
Comment 2 Gerion 2025-04-09 20:03:50 UTC
Can confirm on Gentoo, akonadi-db-migrator 6.3.3 (24.12.3), although I have no symbols in the binary to be able to confirm the stacktrace.
Comment 3 Rongrong 2025-04-24 09:03:02 UTC
I reproduced the issue on Debian sid (akonadi-server 24.12.3) and GDB'd akonadi-db-migrator.

I soonly noticed that the return value of `SchemaVersion::retrieveAll(store)' was an empty QList. This was probably because the migration destination was a newly created database, hence, with all tables being empty at that time.

{
  <QListSpecialMethods<Akonadi::Server::SchemaVersion>> = {
    <QListSpecialMethodsBase<Akonadi::Server::SchemaVersion>> = {<No data fields>}, <No data fields>},
  members of QList<Akonadi::Server::SchemaVersion>:
  d = {
    d = 0x0,
    ptr = 0x0,
    size = 0
  }
}

Then, `.at(0)' immediately extracted a NULL pointer as it never does a bound check (as per https://doc.qt.io/qt-6/qlist.html#at). The NULL pointer was therefore passed to the copy constructor of `Akonadi::Server::SchemaVersion'.

#0  Akonadi::Server::SchemaVersion::SchemaVersion (this=this@entry=0x7ffff25fe0e0, other=...) at ./obj-x86_64-linux-gnu/src/server/entities.cpp:99
#1  0x000055555560b31b in Akonadi::Server::DbInitializer::run (this=0x7fffec037d80) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qarraydatapointer.h:120
#2  0x00005555555de42e in Akonadi::Server::DataStore::init (this=0x7fffec0853c0) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qsharedpointer_impl.h:274
#3  0x00005555555c27d2 in (anonymous namespace)::prepareDatabase (config=config@entry=0x7fffec00ab60) at ./src/server/dbmigrator/dbmigrator.cpp:194
#4  0x00005555555c9341 in Akonadi::Server::DbMigrator::runMigrationThread (this=this@entry=0x7fffffffd490) at ./src/server/dbmigrator/dbmigrator.cpp:533
[...]

I am not familiar with Akonadi. I guess there are two appropriate ways to fix it:
  1. Create a SchemaVersion record immediately after the creation of a new database;
  2. Use `QList::value(0)', which returns a default-constructed value on out-of-bound index.

Could someone familiar with Akonadi fix it (or tell me the appropriate way to fix it so that I can submit an MR)?
Comment 4 Andreas K. Huettel 2025-06-24 12:23:25 UTC
Can confirm on Gentoo, same stacktrace.

#0  0x000055c41d4054a4 in Akonadi::Server::SchemaVersion::SchemaVersion (this=this@entry=0x7f084d3fe3a0, other=...)
    at /var/tmp/portage/kde-apps/akonadi-24.12.3/work/akonadi-24.12.3_build/src/server/entities.cpp:100
#1  0x000055c41d30d13d in Akonadi::Server::DbInitializer::run (this=0x7f084806b9b0) at /usr/include/qt6/QtCore/qarraydatapointer.h:120
#2  0x000055c41d2df532 in Akonadi::Server::DataStore::init (this=0x7f0848030dd0) at /usr/include/qt6/QtCore/qsharedpointer_impl.h:274
#3  0x000055c41d2c4bc2 in (anonymous namespace)::prepareDatabase (config=config@entry=0x7f0848003df0)
    at /var/tmp/portage/kde-apps/akonadi-24.12.3/work/akonadi-24.12.3/src/server/dbmigrator/dbmigrator.cpp:194
#4  0x000055c41d2c9161 in Akonadi::Server::DbMigrator::runMigrationThread (this=0x7fff990d8b10)
    at /var/tmp/portage/kde-apps/akonadi-24.12.3/work/akonadi-24.12.3/src/server/dbmigrator/dbmigrator.cpp:533
#5  0x000055c41d2c9bf6 in operator() (__closure=0x55c45553f1e8) at /var/tmp/portage/kde-apps/akonadi-24.12.3/work/akonadi-24.12.3/src/server/dbmigrator/dbmigrator.cpp:452
#6  0x000055c41d2ca4c9 in std::__invoke_impl<void, Akonadi::Server::DbMigrator::startMigration()::<lambda()> > (__f=<optimized out>)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63
#7  std::__invoke<Akonadi::Server::DbMigrator::startMigration()::<lambda()> > (__fn=<optimized out>) at /usr/lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:98
#8  std::invoke<Akonadi::Server::DbMigrator::startMigration()::<lambda()> > (__fn=<optimized out>) at /usr/lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:122
#9  operator()<> (__closure=<optimized out>) at /usr/include/qt6/QtCore/qthread.h:128
#10 std::__invoke_impl<void, QThread::create<Akonadi::Server::DbMigrator::startMigration()::<lambda()> >(Akonadi::Server::DbMigrator::startMigration()::<lambda()>&&)::<lambda(auto:57&& ...)> >
    (__f=<optimized out>) at /usr/lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63
...
Comment 5 Bernhard Übelacker 2025-09-27 18:29:47 UTC
Hello, got reported downstream for Debian in https://bugs.debian.org/1098891
Comment 6 Stephan Olbrich 2025-10-08 22:18:27 UTC
I run into the same issue but found a workaround:

After running the akonadi-db-migrator a new sqlite db is created with empty tables. I opened it and added the SchemaVersion:

sqlite3 ~/.local/share/akonadi/db_migration/akonadi.db
INSERT INTO SchemaVersionTable (version) VALUES (42);

Then I ran the akonadi-db-migrator again and it migrated successfully to sqlite.
42 is the SchemaVersion. Could change in the future. I picked it from https://invent.kde.org/pim/akonadi/-/blob/master/src/server/storage/akonadidb.xml?ref_type=heads
Make sure you pick the correct one for your akonadi version.
Comment 7 Colin J Thomson 2025-10-13 15:10:43 UTC
*** Bug 497620 has been marked as a duplicate of this bug. ***
Comment 8 Colin J Thomson 2025-10-13 15:16:53 UTC
(In reply to Stephan Olbrich from comment #6)
> I run into the same issue but found a workaround:
> 
> After running the akonadi-db-migrator a new sqlite db is created with empty
> tables. I opened it and added the SchemaVersion:
> 
> sqlite3 ~/.local/share/akonadi/db_migration/akonadi.db
> INSERT INTO SchemaVersionTable (version) VALUES (42);
> 
> Then I ran the akonadi-db-migrator again and it migrated successfully to
> sqlite.
> 42 is the SchemaVersion. Could change in the future. I picked it from
> https://invent.kde.org/pim/akonadi/-/blob/master/src/server/storage/
> akonadidb.xml?ref_type=heads
> Make sure you pick the correct one for your akonadi version.

I just tested your fix and it does work for me as well, thanks for this.

Running KDE from git master:
Operating System: Fedora Linux 43
KDE Plasma Version: 6.5.80
KDE Frameworks Version: 6.20.0
KDE Apps 25.11.70
Qt Version: 6.9.2
Comment 9 Christoph Erhardt 2025-10-16 20:50:48 UTC
Proposed fix: https://invent.kde.org/pim/akonadi/-/merge_requests/293