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

lp1865957: Fetch multiple tracks from MusicBrainz #2534

Merged
merged 25 commits into from
Apr 1, 2020
Merged

lp1865957: Fetch multiple tracks from MusicBrainz #2534

merged 25 commits into from
Apr 1, 2020

Conversation

uklotzde
Copy link
Contributor

@uklotzde uklotzde commented Mar 7, 2020

https://bugs.launchpad.net/mixxx/+bug/1865957

Fixed: Fetching multiple tracks from MusicBrainz while leaving the dialog open.

The WebTask object didn't support the use case to be restarted with a different URL.

@uklotzde
Copy link
Contributor Author

uklotzde commented Mar 7, 2020

CI build failure is unrelated

@uklotzde uklotzde changed the title Hotfix: Fetch multiple tracks from MusicBrainz lp1865957: Fetch multiple tracks from MusicBrainz Mar 7, 2020
src/network/webtask.cpp Outdated Show resolved Hide resolved
@daschuer
Copy link
Member

daschuer commented Mar 9, 2020

If I don't close the music brains window, switch to the Mixxx window in full screen. There is no chance to show the music brains window again. I think it should be moved to the top if you select "fetch Metadata from Musikbrainz" again.

@daschuer
Copy link
Member

daschuer commented Mar 9, 2020

Unfortunately it still segfaults, if you keep the window open:

Warning [Main]: appmenu-qt: handleReparent 143 The given QMenuBar is already registered by appmenu-qt5, skipping
[New Thread 0x7ffea3092700 (LWP 8631)]
[New Thread 0x7ffea27c7700 (LWP 8632)]
Warning [Thread (pooled)]: QObject: Cannot create children for a parent that is in a different thread.
(Parent is TagFetcher(0xac85cc0), parent's thread is QThread(0x14f71c0), current thread is QThread(0x84cd620)
[New Thread 0x7fffc5f88700 (LWP 8633)]
[New Thread 0x7ffea1517700 (LWP 8634)]
Warning [Thread (pooled)]: QObject: Cannot create children for a parent that is in a different thread.
(Parent is TagFetcher(0xac85cc0), parent's thread is QThread(0x14f71c0), current thread is QThread(0x84cd620)
Warning [Main]: appmenu-qt: registerWindow 206 "&Datei"
Warning [Main]: appmenu-qt: registerWindow 206 "&Bibliothek"
Warning [Main]: appmenu-qt: registerWindow 206 "&Ansicht"
Warning [Main]: appmenu-qt: registerWindow 206 "&Optionen"
Warning [Main]: appmenu-qt: registerWindow 206 "&Hilfe"
[Thread 0x7ffea1517700 (LWP 8634) exited]
[Thread 0x7ffea3092700 (LWP 8631) exited]
[New Thread 0x7ffea3092700 (LWP 8656)]
Warning [Thread (pooled)]: QObject: Cannot create children for a parent that is in a different thread.
(Parent is TagFetcher(0xac85cc0), parent's thread is QThread(0x14f71c0), current thread is QThread(0x843ea10)
[New Thread 0x7ffea1517700 (LWP 8659)]
Warning [Thread (pooled)]: QObject: Cannot create children for a parent that is in a different thread.
(Parent is TagFetcher(0xac85cc0), parent's thread is QThread(0x14f71c0), current thread is QThread(0x843ea10)
Warning [Thread (pooled)]: QObject: Cannot create children for a parent that is in a different thread.
(Parent is TagFetcher(0xac85cc0), parent's thread is QThread(0x14f71c0), current thread is QThread(0x843ea10)

Thread 1 "mixxx" received signal SIGSEGV, Segmentation fault.
0x0000000000000030 in ?? ()
(gdb) bt
#0  0x0000000000000030 in ?? ()
#1  0x00007ffff4eadc07 in QMetaObject::invokeMethod (obj=obj@entry=0x15b7910, 
    member=member@entry=0x1105acb "slotAbort", type=4294952288, 
    type@entry=Qt::AutoConnection, ret=..., val0=..., val1=..., val2=..., 
    val3=..., val4=..., val5=..., val6=..., val7=..., val8=..., val9=...)
    at kernel/qmetaobject.cpp:1464
#2  0x0000000000b65e9f in QMetaObject::invokeMethod (val9=..., val8=..., 
    val7=..., val6=..., val5=..., val4=..., val3=..., val2=..., val1=..., 
    val0=..., member=0x1105acb "slotAbort", obj=obj@entry=0x15b7910)
    at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h:425
#3  mixxx::network::WebTask::invokeAbort (this=this@entry=0x15b7910)
    at /home/daniel/workspace/advanced_autodj_2/src/network/webtask.cpp:139
#4  0x0000000000b65eb9 in mixxx::network::WebTask::deleteBeforeFinished (
    this=0x15b7910)
    at /home/daniel/workspace/advanced_autodj_2/src/network/webtask.cpp:147
#5  0x0000000000b52f93 in TagFetcher::abortAcoustIdTask (
    this=this@entry=0xac85cc0)
    at /home/daniel/workspace/advanced_autodj_2/src/musicbrainz/tagfetcher.cpp:42
#6  0x0000000000b5317a in TagFetcher::cancel (this=this@entry=0xac85cc0)
    at /home/daniel/workspace/advanced_autodj_2/src/musicbrainz/tagfetcher.cpp:58
#7  0x0000000000b54045 in TagFetcher::startFetch (this=this@entry=0xac85cc0, 
---Type <return> to continue, or q <return> to quit---
    pTrack=std::shared_ptr (count 4, weak 1) 0xade4210)
    at /home/daniel/workspace/advanced_autodj_2/src/musicbrainz/tagfetcher.cpp:23
#8  0x0000000000a6a0ec in DlgTagFetcher::loadTrack (this=0xac85aa0, 
    track=std::shared_ptr (count 4, weak 1) 0xade4210)
    at /home/daniel/workspace/advanced_autodj_2/src/library/dlgtagfetcher.cpp:99
#9  0x00000000006594b4 in WTrackTableView::slotShowTrackInTagFetcher (
    this=this@entry=0x83c25f0, 
    pTrack=std::shared_ptr (count 4, weak 1) 0xade4210)
    at /home/daniel/workspace/advanced_autodj_2/src/widget/wtracktableview.cpp:817
#10 0x000000000065aaf0 in WTrackTableView::showDlgTagFetcher (
    this=this@entry=0x83c25f0, index=...)
    at /home/daniel/workspace/advanced_autodj_2/src/widget/wtracktableview.cpp:802
#11 0x000000000065ad25 in WTrackTableView::slotNextDlgTagFetcher (
    this=0x83c25f0)
    at /home/daniel/workspace/advanced_autodj_2/src/widget/wtracktableview.cpp:775
#12 0x0000000000705f28 in WTrackTableView::qt_static_metacall (
    _o=_o@entry=0x83c25f0, _c=_c@entry=QMetaObject::InvokeMetaMethod, 
    _id=_id@entry=13, _a=_a@entry=0x7fffffffcc10)
---Type <return> to continue, or q <return> to quit---
    at /home/daniel/workspace/advanced_autodj_2/build/Debug/mixxx-lib_autogen/WFD7YQQOTJ/moc_wtracktableview.cpp:289
#13 0x00007ffff4ecbc0a in QMetaObject::activate (sender=0xac85aa0, 
    signalOffset=<optimized out>, local_signal_index=<optimized out>, 
    argv=<optimized out>) at kernel/qobject.cpp:3713
#14 0x00007ffff4ecba8f in QtPrivate::QSlotObjectBase::call (a=0x7fffffffcd70, 
    r=0xac85aa0, this=<optimized out>)
    at ../../include/QtCore/../../src/corelib/kernel/qobject_impl.h:124
#15 QMetaObject::activate (sender=sender@entry=0xadaf180, 
    signalOffset=<optimized out>, 
    local_signal_index=local_signal_index@entry=2, 
    argv=argv@entry=0x7fffffffcd70) at kernel/qobject.cpp:3698
#16 0x00007ffff4ecc417 in QMetaObject::activate (
    sender=sender@entry=0xadaf180, 
    m=m@entry=0x7ffff60a5a40 <QAbstractButton::staticMetaObject>, 
    local_signal_index=local_signal_index@entry=2, 
    argv=argv@entry=0x7fffffffcd70) at kernel/qobject.cpp:3578
#17 0x00007ffff5f1e2b2 in QAbstractButton::clicked (this=this@entry=0xadaf180, 
    _t1=false) at .moc/moc_qabstractbutton.cpp:303
#18 0x00007ffff5c80f44 in QAbstractButtonPrivate::emitClicked (this=0xadaf1c0)
    at widgets/qabstractbutton.cpp:534
#19 0x00007ffff5c82559 in QAbstractButtonPrivate::click (this=0xadaf1c0)
    at widgets/qabstractbutton.cpp:527
---Type <return> to continue, or q <return> to quit---
#20 0x00007ffff5c826d4 in QAbstractButton::mouseReleaseEvent (this=0xadaf180, 
    e=0x7fffffffd240) at widgets/qabstractbutton.cpp:1132
#21 0x00007ffff5bc6fc8 in QWidget::event (this=0xadaf180, event=0x7fffffffd240)
    at kernel/qwidget.cpp:9044
#22 0x00007ffff5b8405c in QApplicationPrivate::notify_helper (
    this=this@entry=0x153ff10, receiver=receiver@entry=0xadaf180, 
    e=e@entry=0x7fffffffd240) at kernel/qapplication.cpp:3716
#23 0x00007ffff5b89c19 in QApplication::notify (this=<optimized out>, 
    receiver=0xadaf180, e=0x7fffffffd240) at kernel/qapplication.cpp:3276
#24 0x00007ffff4e9d26b in QCoreApplication::notifyInternal (
    this=0x7fffffffdaf0, receiver=receiver@entry=0xadaf180, 
    event=event@entry=0x7fffffffd240) at kernel/qcoreapplication.cpp:965
#25 0x00007ffff5b88b32 in QCoreApplication::sendSpontaneousEvent (
    event=0x7fffffffd240, receiver=0xadaf180)
    at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:227
#26 QApplicationPrivate::sendMouseEvent (receiver=receiver@entry=0xadaf180, 
    event=event@entry=0x7fffffffd240, alienWidget=alienWidget@entry=0xadaf180, 
    nativeWidget=0xac85aa0, 
    buttonDown=buttonDown@entry=0x7ffff60b4b20 <qt_button_down>, 
    lastMouseReceiver=..., spontaneous=true) at kernel/qapplication.cpp:2770
#27 0x00007ffff5be15bb in QWidgetWindow::handleMouseEvent (
    this=this@entry=0xae404e0, event=event@entry=0x7fffffffd650)
    at kernel/qwidgetwindow.cpp:555
---Type <return> to continue, or q <return> to quit---
#28 0x00007ffff5be3b7b in QWidgetWindow::event (this=0xae404e0, 
    event=0x7fffffffd650) at kernel/qwidgetwindow.cpp:210
#29 0x00007ffff5b8405c in QApplicationPrivate::notify_helper (
    this=this@entry=0x153ff10, receiver=receiver@entry=0xae404e0, 
    e=e@entry=0x7fffffffd650) at kernel/qapplication.cpp:3716
#30 0x00007ffff5b89516 in QApplication::notify (this=0x7fffffffdaf0, 
    receiver=0xae404e0, e=0x7fffffffd650) at kernel/qapplication.cpp:3499
#31 0x00007ffff4e9d26b in QCoreApplication::notifyInternal (
    this=0x7fffffffdaf0, receiver=receiver@entry=0xae404e0, 
    event=event@entry=0x7fffffffd650) at kernel/qcoreapplication.cpp:965
#32 0x00007ffff525d4e1 in QCoreApplication::sendSpontaneousEvent (
    event=0x7fffffffd650, receiver=0xae404e0)
    at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:227
#33 QGuiApplicationPrivate::processMouseEvent (e=0x1961a40)
    at kernel/qguiapplication.cpp:1804
#34 0x00007ffff525f1a5 in QGuiApplicationPrivate::processWindowSystemEvent (
    e=e@entry=0x1961a40) at kernel/qguiapplication.cpp:1596
#35 0x00007ffff5242f08 in QWindowSystemInterface::sendWindowSystemEvents (
    flags=...) at kernel/qwindowsysteminterface.cpp:625
#36 0x00007fffe2964200 in userEventSourceDispatch (source=<optimized out>)
    at eventdispatchers/qeventdispatcher_glib.cpp:70
#37 0x00007fffef18c197 in g_main_context_dispatch ()
   from /lib/x86_64-linux-gnu/libglib-2.0.so.0
---Type <return> to continue, or q <return> to quit---
#38 0x00007fffef18c3f0 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#39 0x00007fffef18c49c in g_main_context_iteration ()
   from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#40 0x00007ffff4ef36af in QEventDispatcherGlib::processEvents (this=0x165f860, 
    flags=...) at kernel/qeventdispatcher_glib.cpp:418
#41 0x00007ffff4e9aa2a in QEventLoop::exec (this=this@entry=0x7fffffffd9d0, 
    flags=..., flags@entry=...) at kernel/qeventloop.cpp:204
#42 0x00007ffff4ea2acc in QCoreApplication::exec ()
    at kernel/qcoreapplication.cpp:1229
#43 0x00007ffff5254bfc in QGuiApplication::exec ()
    at kernel/qguiapplication.cpp:1542
#44 0x00007ffff5b80495 in QApplication::exec () at kernel/qapplication.cpp:2976
#45 0x0000000000484b89 in (anonymous namespace)::runMixxx (args=..., 
    app=0x7fffffffdaf0)
    at /home/daniel/workspace/advanced_autodj_2/src/main.cpp:53
#46 main (argc=1, argv=<optimized out>)
    at /home/daniel/workspace/advanced_autodj_2/src/main.cpp:130
(gdb) 

I need to check if QMetaObject::invokeMethod() for Qt < 5.10 works differently.

Update: Invocation of method by name (old version) works as expected in Qt 5.13.2, no issues.

@uklotzde
Copy link
Contributor Author

uklotzde commented Mar 9, 2020

If I don't close the music brains window, switch to the Mixxx window in full screen. There is no chance to show the music brains window again. I think it should be moved to the top if you select "fetch Metadata from Musikbrainz" again.

I cannot confirm this. Switching into fullscreen mode works even while the window is open. The window handling has not been changed.

@ronso0
Copy link
Member

ronso0 commented Mar 9, 2020

If I don't close the music brains window, switch to the Mixxx window in full screen. There is no chance to show the music brains window again. I think it should be moved to the top if you select "fetch Metadata from Musikbrainz" again.

I read about (and experienced myself) a few window management issues, like the mapping wizard window being hidden behind Mixxx during mapping (Ubuntu 18.04). If Uwe can't reproduce with fedora this seems to be OS specific.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you confirm the crash?

@uklotzde
Copy link
Contributor Author

Can you confirm the crash?

No, that's why I asked for detailed instructions. Maybe there is some subtle special case that I didn't account for?

@uklotzde
Copy link
Contributor Author

I can randomly click on the Previous and Next buttons to abort running requests and trigger new request in DlgTagFetcher. Not any issues independent of the frequency of abusing those buttons, everything works perfectly and stable.

@uklotzde
Copy link
Contributor Author

Can anyone else reproduce this crash???

The affected pointers are managed and checked by our parented_ptr and the deletion is triggered by QObject::deleteLater(). Thus the crash cannot be caused by use-after-tree if those mechanisms work as expected.

@uklotzde
Copy link
Contributor Author

@daschuer Are your sure that you tested a consistent build?

Copy link
Member

@Holzhaus Holzhaus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good, the branch builds fine and tests still pass. I cannot reproduce any crashes that @daschuer mentioned.

Maybe that window should be modal to avoid confusion when another track is selected and the user does not know which track the fetched metadata applies to, but that's not in scope of this PR.

LGTM, thank you!

@uklotzde
Copy link
Contributor Author

@daschuer Ping

@uklotzde
Copy link
Contributor Author

uklotzde commented Mar 20, 2020

@daschuer Last attempt to get feedback. I installed a VM with Ubuntu 18.04 LTS, compiled this branch and manually tested. Not a single crash.

@daschuer
Copy link
Member

Sorry for the delay, I hope I will find time to look into this tonight.

@daschuer
Copy link
Member

I was able to reproduce the crasher. It happens when hammering the next button.
First the Dialog stalls and after pressing the previous button i got:

Debug [Main]: GlobalTrackCache - Evicting track ["/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" | "/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" | 42] Track(0xce87f30)
Debug [Main]: TrackCollectionManager - Saving track "/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" in internal collection
Debug [Main]: TrackDAO: Saving track 42 "/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3"
Debug [Main]: TrackDAO: Updating track in database 42 "/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3"
Debug [Main]: SqlTransaction - Started new SQL database transaction on "MIXXX-1"
Debug [Main]: SqlTransaction - Committed SQL database transaction on "MIXXX-1"
Debug [Main]: BaseTrackCache(0x3e4a410) updateIndexWithQuery took 0 ms
Debug [Main]: GlobalTrackCache - Deleting Track(0xce87f30)
Debug [Main]: GlobalTrackCache - Resolving track by id 42
Debug [Main]: GlobalTrackCache - Resolving track by canonical location "/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3"
Debug [Main]: GlobalTrackCache - Cache miss - allocating track ["/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" | "/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" | 42]
Debug [Main]: GlobalTrackCache - Cache miss - inserting new track into cache ["/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" | "/home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" | 42] QObject(0x0)
Debug [Main]: Successfully deserialized BeatGrid
Debug [Main]: Successfully deserialized KeyMap
Debug [Main]: SoundSourceProxy - SoundSourceProvider "MAD: MPEG Audio Decoder" created a SoundSource for file "file:///home/daniel/Musik/Fear Factory - Linchpin (weitere Kopie)_.mp3" of type "mp3"
Debug [Main]: BaseTrackCache(0x3e4a410) updateIndexWithQuery took 0 ms

Thread 1 "mixxx" received signal SIGSEGV, Segmentation fault.
0x00007ffff4eadc05 in QMetaObject::invokeMethod (obj=obj@entry=0xce60970, 
    member=member@entry=0x1121ceb "slotAbort", type=4294952176, 
    type@entry=Qt::AutoConnection, ret=..., val0=..., val1=..., val2=..., 
    val3=..., val4=..., val5=..., val6=..., val7=..., val8=..., val9=...)
    at kernel/qmetaobject.cpp:1464
1464	kernel/qmetaobject.cpp: Datei oder Verzeichnis nicht gefunden.
(gdb) bt
#0  0x00007ffff4eadc05 in QMetaObject::invokeMethod (obj=obj@entry=0xce60970, 
    member=member@entry=0x1121ceb "slotAbort", type=4294952176, 
    type@entry=Qt::AutoConnection, ret=..., val0=..., val1=..., val2=..., 
    val3=..., val4=..., val5=..., val6=..., val7=..., val8=..., val9=...)
    at kernel/qmetaobject.cpp:1464
#1  0x0000000000b74c6f in QMetaObject::invokeMethod (val9=..., val8=..., 
    val7=..., val6=..., val5=..., val4=..., val3=..., val2=..., val1=..., 
    val0=..., member=0x1121ceb "slotAbort", obj=obj@entry=0xce60970)
    at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h:425
#2  mixxx::network::WebTask::invokeAbort (this=this@entry=0xce60970)
    at /home/daniel/workspace/advanced_autodj_2/src/network/webtask.cpp:139
#3  0x0000000000b74c89 in mixxx::network::WebTask::deleteBeforeFinished (
    this=0xce60970)
    at /home/daniel/workspace/advanced_autodj_2/src/network/webtask.cpp:147
#4  0x0000000000b61d63 in TagFetcher::abortAcoustIdTask (
    this=this@entry=0xcdc1110)
    at /home/daniel/workspace/advanced_autodj_2/src/musicbrainz/tagfetcher.cpp:42
#5  0x0000000000b61f4a in TagFetcher::cancel (this=this@entry=0xcdc1110)
    at /home/daniel/workspace/advanced_autodj_2/src/musicbrainz/tagfetcher.cpp:58
#6  0x0000000000b62e15 in TagFetcher::startFetch (this=this@entry=0xcdc1110, 
    pTrack=std::shared_ptr (count 4, weak 1) 0xce8e9e0)
---Type <return> to continue, or q <return> to quit---
    at /home/daniel/workspace/advanced_autodj_2/src/musicbrainz/tagfetcher.cpp:23
#7  0x0000000000a7704c in DlgTagFetcher::loadTrack (this=0xcdc0ef0, 
    track=std::shared_ptr (count 4, weak 1) 0xce8e9e0)
    at /home/daniel/workspace/advanced_autodj_2/src/library/dlgtagfetcher.cpp:99
#8  0x000000000065f254 in WTrackTableView::slotShowTrackInTagFetcher (
    this=this@entry=0x84685d0, 
    pTrack=std::shared_ptr (count 4, weak 1) 0xce8e9e0)
    at /home/daniel/workspace/advanced_autodj_2/src/widget/wtracktableview.cpp:818
#9  0x00000000006603c0 in WTrackTableView::showDlgTagFetcher (
    this=this@entry=0x84685d0, index=...)
    at /home/daniel/workspace/advanced_autodj_2/src/widget/wtracktableview.cpp:803
#10 0x000000000066a3c5 in WTrackTableView::slotPrevDlgTagFetcher (
    this=0x84685d0)
    at /home/daniel/workspace/advanced_autodj_2/src/widget/wtracktableview.cpp:787
#11 0x000000000070bfcc in WTrackTableView::qt_static_metacall (
    _o=_o@entry=0x84685d0, _c=_c@entry=QMetaObject::InvokeMetaMethod, 
    _id=_id@entry=15, _a=_a@entry=0x7fffffffcba0)
    at /home/daniel/workspace/advanced_autodj_2/build/Debug/mixxx-lib_autogen/WF---Type <return> to continue, or q <return> to quit---
D7YQQOTJ/moc_wtracktableview.cpp:291
#12 0x00007ffff4ecbc0a in QMetaObject::activate (sender=0xcdc0ef0, 
    signalOffset=<optimized out>, local_signal_index=<optimized out>, 
    argv=<optimized out>) at kernel/qobject.cpp:3713
#13 0x00007ffff4ecba8f in QtPrivate::QSlotObjectBase::call (a=0x7fffffffcd00, 
    r=0xcdc0ef0, this=<optimized out>)
    at ../../include/QtCore/../../src/corelib/kernel/qobject_impl.h:124
#14 QMetaObject::activate (sender=sender@entry=0xcdb8f40, 
    signalOffset=<optimized out>, 
    local_signal_index=local_signal_index@entry=2, 
    argv=argv@entry=0x7fffffffcd00) at kernel/qobject.cpp:3698
#15 0x00007ffff4ecc417 in QMetaObject::activate (
    sender=sender@entry=0xcdb8f40, 
    m=m@entry=0x7ffff60a5a40 <QAbstractButton::staticMetaObject>, 
    local_signal_index=local_signal_index@entry=2, 
    argv=argv@entry=0x7fffffffcd00) at kernel/qobject.cpp:3578
#16 0x00007ffff5f1e2b2 in QAbstractButton::clicked (this=this@entry=0xcdb8f40, 
    _t1=false) at .moc/moc_qabstractbutton.cpp:303
#17 0x00007ffff5c80f44 in QAbstractButtonPrivate::emitClicked (this=0xcdb9740)
    at widgets/qabstractbutton.cpp:534
#18 0x00007ffff5c82559 in QAbstractButtonPrivate::click (this=0xcdb9740)
    at widgets/qabstractbutton.cpp:527
#19 0x00007ffff5c826d4 in QAbstractButton::mouseReleaseEvent (this=0xcdb8f40, 
---Type <return> to continue, or q <return> to quit---
    e=0x7fffffffd1d0) at widgets/qabstractbutton.cpp:1132
#20 0x00007ffff5bc6fc8 in QWidget::event (this=0xcdb8f40, event=0x7fffffffd1d0)
    at kernel/qwidget.cpp:9044
#21 0x00007ffff5b8405c in QApplicationPrivate::notify_helper (
    this=this@entry=0x1565440, receiver=receiver@entry=0xcdb8f40, 
    e=e@entry=0x7fffffffd1d0) at kernel/qapplication.cpp:3716
#22 0x00007ffff5b89c19 in QApplication::notify (this=<optimized out>, 
    receiver=0xcdb8f40, e=0x7fffffffd1d0) at kernel/qapplication.cpp:3276
#23 0x00007ffff4e9d26b in QCoreApplication::notifyInternal (
    this=0x7fffffffda80, receiver=receiver@entry=0xcdb8f40, 
    event=event@entry=0x7fffffffd1d0) at kernel/qcoreapplication.cpp:965
#24 0x00007ffff5b88b32 in QCoreApplication::sendSpontaneousEvent (
    event=0x7fffffffd1d0, receiver=0xcdb8f40)
    at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:227
#25 QApplicationPrivate::sendMouseEvent (receiver=receiver@entry=0xcdb8f40, 
    event=event@entry=0x7fffffffd1d0, alienWidget=alienWidget@entry=0xcdb8f40, 
    nativeWidget=0xcdc0ef0, 
    buttonDown=buttonDown@entry=0x7ffff60b4b20 <qt_button_down>, 
    lastMouseReceiver=..., spontaneous=true) at kernel/qapplication.cpp:2770
#26 0x00007ffff5be15bb in QWidgetWindow::handleMouseEvent (
    this=this@entry=0xcd2f180, event=event@entry=0x7fffffffd5e0)
    at kernel/qwidgetwindow.cpp:555
#27 0x00007ffff5be3b7b in QWidgetWindow::event (this=0xcd2f180, 
---Type <return> to continue, or q <return> to quit---
    event=0x7fffffffd5e0) at kernel/qwidgetwindow.cpp:210
#28 0x00007ffff5b8405c in QApplicationPrivate::notify_helper (
    this=this@entry=0x1565440, receiver=receiver@entry=0xcd2f180, 
    e=e@entry=0x7fffffffd5e0) at kernel/qapplication.cpp:3716
#29 0x00007ffff5b89516 in QApplication::notify (this=0x7fffffffda80, 
    receiver=0xcd2f180, e=0x7fffffffd5e0) at kernel/qapplication.cpp:3499
#30 0x00007ffff4e9d26b in QCoreApplication::notifyInternal (
    this=0x7fffffffda80, receiver=receiver@entry=0xcd2f180, 
    event=event@entry=0x7fffffffd5e0) at kernel/qcoreapplication.cpp:965
#31 0x00007ffff525d4e1 in QCoreApplication::sendSpontaneousEvent (
    event=0x7fffffffd5e0, receiver=0xcd2f180)
    at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:227
#32 QGuiApplicationPrivate::processMouseEvent (e=0xce32f70)
    at kernel/qguiapplication.cpp:1804
#33 0x00007ffff525f1a5 in QGuiApplicationPrivate::processWindowSystemEvent (
    e=e@entry=0xce32f70) at kernel/qguiapplication.cpp:1596
#34 0x00007ffff5242f08 in QWindowSystemInterface::sendWindowSystemEvents (
    flags=...) at kernel/qwindowsysteminterface.cpp:625
#35 0x00007fffe2964200 in userEventSourceDispatch (source=<optimized out>)
    at eventdispatchers/qeventdispatcher_glib.cpp:70
#36 0x00007fffef18c197 in g_main_context_dispatch ()
   from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#37 0x00007fffef18c3f0 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
---Type <return> to continue, or q <return> to quit---
#38 0x00007fffef18c49c in g_main_context_iteration ()
   from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#39 0x00007ffff4ef36af in QEventDispatcherGlib::processEvents (this=0x167b160, 
    flags=...) at kernel/qeventdispatcher_glib.cpp:418
#40 0x00007ffff4e9aa2a in QEventLoop::exec (this=this@entry=0x7fffffffd960, 
    flags=..., flags@entry=...) at kernel/qeventloop.cpp:204
#41 0x00007ffff4ea2acc in QCoreApplication::exec ()
    at kernel/qcoreapplication.cpp:1229
#42 0x00007ffff5254bfc in QGuiApplication::exec ()
    at kernel/qguiapplication.cpp:1542
#43 0x00007ffff5b80495 in QApplication::exec () at kernel/qapplication.cpp:2976
#44 0x0000000000485cf9 in (anonymous namespace)::runMixxx (args=..., 
    app=0x7fffffffda80)
    at /home/daniel/workspace/advanced_autodj_2/src/main.cpp:53
#45 main (argc=2, argv=<optimized out>)
    at /home/daniel/workspace/advanced_autodj_2/src/main.cpp:130

@daschuer
Copy link
Member

A fix is in progress

@uklotzde
Copy link
Contributor Author

I'm curious for the results and would like to know for which Qt version the crash occurs. No matter how fast or often I hammer the Previous/Next buttons, not a single crash yet.

@daschuer
Copy link
Member

This fixes the issue:
https://github.com/uklotzde/mixxx/pull/11

@daschuer
Copy link
Member

I will also do a review. I am afraid there are some issues left.

@Holzhaus
Copy link
Member

Holzhaus commented Mar 27, 2020

I just tested and also spammed the previous/next button. All requests seems to work nicely, I didn't encounter any crashes or debug asserts.

However, when I actually apply the metadata there seems to be a problem: After applying the new metadata it does show up in the library view. When I then select another track and then select the track I just applied the metadata to, the metadata gets reset to the state before the musicbrainz import (at least the title/artist fields in the library view). Might be unrelated to this branch and also be caused by the caching issue, I don't know.

@uklotzde
Copy link
Contributor Author

uklotzde commented Mar 27, 2020

@Holzhaus Commit e2740ba should have fixed this issue. I tested it successfully, but there might be other issues?

@Holzhaus
Copy link
Member

@Holzhaus Commit e2740ba should have fixed this issue. I tested it successfully, but there might be other issues?

Sorry, I forgot to pull your latest changes apparently. Yes, the issue has been fixed.

@uklotzde
Copy link
Contributor Author

SIGSEGV in another context, not sure if related and how:

_ZN11QMetaObject12invokeMethodIZN5mixxx7network7WebTask11invokeAbortEvE3$_3EENSt9enable_ifIXaaaantsr9QtPrivate15FunctionPointerIT_EE25IsPointerToMemberFunctioneqsr9QtPrivate15FunctionPointerIS6_EE13ArgumentCountngLi1Entsr3std14is_convertibleIS6_PKcEE5valueEbE4typeEP7QObjectS6_N2Qt14ConnectionTypeEPDTclfL0p0_EE
    (context=0x120697a0, function=..., type=Qt::AutoConnection, ret=0x0) at /usr/include/qt5/QtCore/qobjectdefs.h:529
#3  0x0000000000b53e76 in mixxx::network::WebTask::invokeAbort() (this=0x120697a0) at /tmp/mixxx/src/network/webtask.cpp:151
#4  0x0000000000b53f3c in mixxx::network::WebTask::deleteBeforeFinished() (this=0x120697a0) at /tmp/mixxx/src/network/webtask.cpp:168
#5  0x0000000000cc36ed in mixxx::aoide::TrackTableModel::abortPendingSearch() (this=0x15ec800) at /tmp/mixxx/src/library/aoide/tracktablemodel.cpp:399
#6  0x0000000000cc3909 in mixxx::aoide::TrackTableModel::searchTracks(QJsonObject, QString) (this=0x15ec800, baseQuery=..., searchText=...)
    at /tmp/mixxx/src/library/aoide/tracktablemodel.cpp:426
#7  0x0000000000c83429 in mixxx::aoide::LibraryFeature::activateChild(QModelIndex const&) (this=0x404ea90, index=...) at /tmp/mixxx/src/library/aoide/libraryfeature.cpp:229

This is the first time this ever happened.

@@ -38,15 +38,15 @@ void TagFetcher::startFetch(

void TagFetcher::abortAcoustIdTask() {
if (m_pAcoustIdTask) {
disconnect(m_pAcoustIdTask.get());
disconnect(m_pAcoustIdTask);
m_pAcoustIdTask->deleteBeforeFinished();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The crash happens here. The operator-> returns the plain pointer here in the GUI thread. If the thread is suspended and the delete from the worker thread happens in between, than the pointer becomes dangling an the crash occurs.
https://github.com/uklotzde/mixxx/pull/11 fixes the issue.
I strongly recommend to remove all auto deletion code as done in the PR.
If you need fire and forget nature in your other branches, inhered from the classes and add the desired nature.
It is kind of unpredictable and hard to review to have bot concepts mixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The self-destruction code is now enclosed in VERFIY_AND_DEBUG_ASSERT to ensure that no unhandled signals slip through. It only serves as a fallback to prevent memory leaks.

I still don't understand how a crash could happen when using deleteLater(). This should ensure that objects remain alive until all signal handling has finished and control has been returned to the event loop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope I can explain:

DeleteLater sends a signal to the object that calls a slot that deletes the object from the thread the object lives in. This ensures that all signals that have been issued before and might be still in the queue are executed before deletion, which would lead to a crash in the best case.

Since Qt5 Qt uses it's QWeakPointer and QSharedPointer internally to maintain the object tree. This works with less locking than the Qt4 approach, that utilizes signals and slots.
A QPointer is essential a wrapper around Qt's weak pointer. It becomes a nullptr at any time once the last reference to the object was removed.

The code of question can be also written like this:

    if (m_pAcoustIdTask) {
        disconnect(m_pAcoustIdTask);
        m_pAcoustIdTask->deleteBeforeFinished();

Can be also written inlined as:

    if (m_pAcoustIdTask) {
        disconnect(m_pAcoustIdTask);
        mixxx::AcoustIdLookupTask pTask = m_pAcoustIdTask.data();
       QMetaObject::invokeMethod([] {pTask->slotAbort();  })

The crash happens if the object is deleted from the other thread just between the last two lines. m_pAcoustIdTask.data() returns the still valid pointer 0x120697a0 but it becomes dangling before pTask->slotAbort() is called.

The DeleteLater trick dos not help here, because the object is already gone.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these signal and slots are hard to follow.
This is IMHO the major disadvantage of using a QT event loop for a worker thread.
Please ensure that every code path ends with either a success or a failure signal.
This also includes the early exists with VERIFY_OR_DEBUG_ASSERT.

src/musicbrainz/tagfetcher.cpp Outdated Show resolved Hide resolved
src/musicbrainz/tagfetcher.cpp Outdated Show resolved Hide resolved
src/musicbrainz/tagfetcher.cpp Outdated Show resolved Hide resolved
src/network/webtask.cpp Show resolved Hide resolved
@uklotzde uklotzde changed the title lp1865957: Fetch multiple tracks from MusicBrainz [WiP] lp1865957: Fetch multiple tracks from MusicBrainz Apr 1, 2020
@uklotzde uklotzde changed the title [WiP] lp1865957: Fetch multiple tracks from MusicBrainz lp1865957: Fetch multiple tracks from MusicBrainz Apr 1, 2020
@uklotzde
Copy link
Contributor Author

uklotzde commented Apr 1, 2020

Done.

I have added lots of assertions to check for spurious, unexpected signals. This hopefully prevents future regressions if anyone tries to adjust the inner workings of TagFetcher. Experience has shown that this could be tricky including unforeseeable interactions.

@daschuer
Copy link
Member

daschuer commented Apr 1, 2020

Great. The code looks good and more important it works really good.
I don't even see the timeouts after three tracks anymore.
What I now get If I hammering to much on the next button is a "Service temporary unavailable message" I guess this one was silently discarded in the previous version, which has probably messed up the state machine.

@daschuer daschuer merged commit b717efe into mixxxdj:master Apr 1, 2020
@uklotzde uklotzde deleted the restart_webtask branch April 1, 2020 23:13
@uklotzde
Copy link
Contributor Author

uklotzde commented Apr 2, 2020

@daschuer Thank you for your review patience! I was struggling really hard to find a solution that is acceptable for both of us. Glad that it worked out in the end.

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

Successfully merging this pull request may close these issues.

5 participants