Bug 494924 - Racy crash during a session in (anonymous namespace)::sendChangedSignal (updatedFiles=...)
Summary: Racy crash during a session in (anonymous namespace)::sendChangedSignal (upda...
Status: REOPENED
Alias: None
Product: frameworks-baloo
Classification: Frameworks and Libraries
Component: Baloo File Daemon (other bugs)
Version First Reported In: 6.7.0
Platform: Fedora RPMs Linux
: NOR crash
Target Milestone: ---
Assignee: baloo-bugs-null
URL: https://bugreports.qt.io/browse/QTBUG...
Keywords:
Depends on:
Blocks:
 
Reported: 2024-10-17 11:03 UTC by postix
Modified: 2024-10-17 23:59 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments
full backtrace (24.13 KB, text/plain)
2024-10-17 11:03 UTC, postix
Details

Note You need to log in before you can comment on or make changes to this bug.
Description postix 2024-10-17 11:03:44 UTC
Created attachment 174934 [details]
full backtrace

SUMMARY

While more or less idling, Baloo suddenly crashed (#16). Could also be a Qt bug though.

```
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=11, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007f0ed10a86d3 in __pthread_kill_internal (threadid=<optimized out>, signo=11) at pthread_kill.c:78
#2  0x00007f0ed104fc4e in __GI_raise (sig=11) at ../sysdeps/posix/raise.c:26
#3  0x00007f0ed21861a2 in KCrash::defaultCrashHandler (sig=11) at /usr/src/debug/kf6-kcrash-6.7.0-1.fc40.x86_64/src/kcrash.cpp:596
#4  <signal handler called>
#5  QUtf8::convertFromUnicode (in=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/text/qstringconverter.cpp:490
#6  0x00007f0ed1890238 in qt_convert_to_utf8 (str=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/text/qstring.cpp:5666
#7  QString::toUtf8_helper (str=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/text/qstring.cpp:5658
#8  0x00007f0ed1e3e226 in QString::toUtf8() const & (this=0x7f0ebe5ff338) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/text/qstring.h:619
#9  QDBusMarshaller::append (this=this@entry=0x7f0ebe5ff350, arg=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/dbus/qdbusmarshaller.cpp:102
#10 0x00007f0ed1e4082f in QDBusMarshaller::append (this=0x55b65734e068, arg=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/dbus/qdbusmarshaller.cpp:210
#11 QDBusMarshaller::appendVariantInternal (this=this@entry=0x7f0ebe5ff530, arg=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/dbus/qdbusmarshaller.cpp:446
#12 0x00007f0ed1e77caf in QDBusMessagePrivate::toDBusMessage (message=..., capabilities=..., error=error@entry=0x7f0ebe5ff7f0)
    at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/dbus/qdbusmessage.cpp:178
#13 0x00007f0ed1e529a1 in QDBusConnectionPrivate::send (this=0x7f0eb8001450, message=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/global/qflags.h:34
#14 0x00007f0ed1e53077 in QDBusConnectionPrivate::send (this=<optimized out>, message=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/dbus/qdbusintegrator.cpp:1967
#15 0x00007f0ed1e43f5e in QDBusConnection::send (this=<optimized out>, message=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/dbus/qdbusconnection.cpp:316
#16 0x000055b655c6bfdf in (anonymous namespace)::sendChangedSignal (updatedFiles=...) at /usr/src/debug/kf6-baloo-6.7.0-1.fc40.x86_64/src/file/filecontentindexer.cpp:27
#17 Baloo::FileContentIndexer::run (this=<optimized out>) at /usr/src/debug/kf6-baloo-6.7.0-1.fc40.x86_64/src/file/filecontentindexer.cpp:103
#18 0x00007f0ed195d923 in QThreadPoolThread::run (this=0x55b65728ad80) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/thread/qthreadpool.cpp:68
#19 0x00007f0ed195473c 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
#20 (anonymous namespace)::terminate_on_exception<QThreadPrivate::start(void*)::<lambda()> > (t=...)
    at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/thread/qthread_unix.cpp:262
#21 QThreadPrivate::start (arg=0x55b65728ad80) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/thread/qthread_unix.cpp:285
#22 0x00007f0ed10a66d7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#23 0x00007f0ed112a60c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78
```


SOFTWARE/OS VERSIONS
Operating System: Fedora Linux 40
KDE Plasma Version: 6.2.0
KDE Frameworks Version: 6.7.0
Qt Version: 6.7.2
Kernel Version: 6.11.3-200.fc40.x86_64 (64-bit)
Graphics Platform: Wayland
Comment 1 postix 2024-10-17 11:08:12 UTC
Looks like this is actually a Qt memory access bug:

```
QUtf8::convertFromUnicode (in=...) at /usr/src/debug/qt6-qtbase-6.7.2-6.fc40.x86_64/src/corelib/text/qstringconverter.cpp:490
        u = <optimized out>
        res = <optimized out>
        nextAscii = 0x3 <error: Cannot access memory at address 0x3>
        len = <optimized out>
        result = {d = {d = 0x7eceb0005e50, ptr = 0x7eceb0005e60 "", size = 3}, static _empty = 0 '\000'}
        dst = 0x7eceb0005e60 ""
        src = 0x1 <error: Cannot access memory at address 0x1>
        end = <optimized out>
```

Will check if it's known, otherwise report it upstream and reference it here.
Comment 2 postix 2024-10-17 20:22:13 UTC
Thiago Macieira from Qt has done an incredible job in analyzing the backtrace, see the link in URL field above:

> The outermost frame that you pasted is not QtDBus code
>  (filecontentindexer.cpp:27 and RIP = 0x000055b655c6bfdf,
> indicating code located in the main executable
> [unless you have Clear Linux's optimisations, which you don't]).
> This means this content is not running in the QDBusConnectionManager
>  thread, so this is not a QtDBus race condition either.

> That frame is 
> https://invent.kde.org/frameworks/baloo/-/blob/master/src/file/filecontentindexer.cpp#L21-28:
```
 void sendChangedSignal(const QStringList& updatedFiles)
    {
        auto message = QDBusMessage::createSignal(QStringLiteral("/files"),
                                                  QStringLiteral("org.kde"),
                                                  QStringLiteral("changed"));
        message.setArguments({updatedFiles});
        QDBusConnection::sessionBus().send(message);
    }
```

> As far as I can tell, the corruption happened above this too. This QStringList is pointing to garbage.

> https://retrace.fedoraproject.org/faf/reports/1035460/ 
> says this is running on a thread running Baloo::FileContentIndexer::run():
```
            // Notify some metadata may have changed
            sendChangedSignal(m_updatedFiles);
            m_updatedFiles.clear();
```
> Aside from the run() function itself, m_updatedFiles is modified in
>  FileContentIndexer::slotFinishedIndexingFile, which is connected
> at the beginning of the run() function:
```
    ExtractorProcess process{m_extractorPath};
    connect(&process, &ExtractorProcess::startedIndexingFile, this, &FileContentIndexer::slotStartedIndexingFile);
    connect(&process, &ExtractorProcess::finishedIndexingFile, this, &FileContentIndexer::slotFinishedIndexingFile);
```
> FileContentIndexer is a public QObject, public QRunnable.
> It is used as a member in FileIndexScheduler (m_contentIndexer). 
> There's no call to moveToThread in Baloo anywhere and QThreadPool will not do it for you.
> This means that Qt::AutoConnection connection above will resolve as a Qt::QueuedConnection
> and deliver the signal to the thread where FileIndexScheduler was created, 
> not the one the FileContentIndexer runnable is running on. 
> Since FileContentIndexer::slotFinishedIndexingFile does not lock any mutexes, this is the race condition

> This can be fixed by adding Qt::DirectConnection to the two connect statements above.