Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt Assert failure: sendEvent across threads #4009

Closed
lukas-w opened this issue Nov 24, 2017 · 4 comments
Closed

Qt Assert failure: sendEvent across threads #4009

lukas-w opened this issue Nov 24, 2017 · 4 comments
Labels

Comments

@lukas-w
Copy link
Member

lukas-w commented Nov 24, 2017

From #4000:

An assertion inside Qt fails when releasing a preview note (from presets, instrument window, or piano roll). Opening a demo project and playing works fine.

ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 5c86fd0. Receiver '' (of type 'TrackContentObject') was created in thread 37b220", file kernel\qcoreapplication.cpp, line 541
QObject::~QObject: Timers cannot be stopped from another thread

This can only be reproduced with a debug build of Qt.

Backtrace:

1  qt_message_fatal                                qlogging.cpp          1681 0x6705a78b  
2  QMessageLogger::fatal                           qlogging.cpp          795  0x67058fb2  
3  qt_assert_x                                     qglobal.cpp           3078 0x6704c6e1  
4  QCoreApplicationPrivate::checkReceiverThread    qcoreapplication.cpp  533  0x6742e9be  
5  QApplication::notify                            qapplication.cpp      2970 0x64101974  
6  QCoreApplication::notifyInternal2               qcoreapplication.cpp  988  0x6742cd16  
7  QCoreApplication::sendEvent                     qcoreapplication.h    231  0x67437ca2  
8  QObjectPrivate::setParent_helper                qobject.cpp           1996 0x6748ad40  
9  QObject::~QObject                               qobject.cpp           1048 0x67484d4a  
10 Model::~Model                                   Model.cpp             30   0x13f55c03a 
11 AutomatableModel::~AutomatableModel             AutomatableModel.cpp  84   0x13f4ba91b 
12 BoolModel::~BoolModel                           lmms                       0x13f4a5338 
13 TrackContentObject::~TrackContentObject         Track.cpp             130  0x13f5a0ddf 
14 AutomationPattern::~AutomationPattern           AutomationPattern.cpp 106  0x13f4c30c6 
15 AutomationPattern::`vector deleting destructor' lmms                       0x13f4cae68 
16 InlineAutomation::~InlineAutomation             InlineAutomation.h    46   0x13f55dfb7 
17 DetuningHelper::~DetuningHelper                 DetuningHelper.h      44   0x13f55defa 
18 DetuningHelper::`scalar deleting destructor'    lmms                       0x13f55e25c 
19 sharedObject::unref<DetuningHelper>             shared_object.h       64   0x13f55dc42 
20 Note::~Note                                     Note.cpp              89   0x13f55c710 
21 NotePlayHandle::~NotePlayHandle                 NotePlayHandle.cpp    163  0x13f55eff1 
22 NotePlayHandleManager::release                  NotePlayHandle.cpp    603  0x13f560b48 
23 Mixer::renderNextBuffer                         Mixer.cpp             457  0x13f54fb31 
24 Mixer::fifoWriter::run                          Mixer.cpp             1103 0x13f54db6f 
25 QThreadPrivate::start                           qthread_win.cpp       380  0x670804e6  
26 BaseThreadInitThunk                             kernel32                   0x770159cd  
27 RtlUserThreadStart                              ntdll                      0x7714a561                                                                                

Looks like some object lives in a different thread than its parent, which is disallowed by Qt. I'm not sure how that's possible, because Qt usually prevents it from happening. When destructed, the child tries to notify its parent using QCoreApplication::sendEvent (qobject.cpp line 1996):

QChildEvent e(QEvent::ChildRemoved, q);
QCoreApplication::sendEvent(parent, &e);
@lukas-w lukas-w added the bug label Nov 24, 2017
@PhysSong
Copy link
Member

I think there should be NotePlayHandle::~NotePlayHandle in <More>.

from presets, instrument window, or piano roll

It means "from UI thread". So NotePlayHandle and related instances(including BoolModel which inherits QObject) will be constructed in the UI thread. However, every PlayHandle instances are deleted in Mixer thread, which causes this assertion failure.
Note that this was not present before #3884, because of the wrong design of NotePlayHandleManager. It never called NotePlayHandle destructor, which is not correct. I wonder whether it existed before #1088, which introduced the wrong design I mentioned.

@PhysSong
Copy link
Member

I just found this should be able to reproduced without #3884. With 1.2.0-rc4(or not too older), you should be able to trigger this by previewing audio samples(#3884 was merged after rc4).

@lukas-w
Copy link
Member Author

lukas-w commented Nov 24, 2017

I think there should be NotePlayHandle::~NotePlayHandle in .

Correct. I edited my comment to include the full stack trace.

Thanks for investigating. 👍 I think this can be fixed by just using deleteLater in sharedObject::unref().

lukas-w added a commit that referenced this issue Nov 24, 2017
This makes unref safe when it's not called from within the object's thread.

Fixes #4009
@lukas-w lukas-w closed this as completed Nov 27, 2017
@lukas-w
Copy link
Member Author

lukas-w commented Nov 27, 2017

Fixed via #4010

sdasda7777 pushed a commit to sdasda7777/lmms that referenced this issue Jun 28, 2022
This makes unref safe when it's not called from within the object's thread.

Fixes LMMS#4009
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants