Issue with ThreadWithProgressWindow


#1

Hi Jules,

I’m having a crash related to ThreadWithProgressWindow

I have a browser component with a ThreadWithProgressWindow and a close button which delete this browser. (The ThreadWithProgressWindow is a member var of the browser component)

If I click a lot of time on this close button while loading, when the loading end and I click the button perfectly in time, it crashes.

Indeed, as soon as the thread is finished, it calls in the same round runDispatchLoopUntil so the mouse up on my button is called which trigger the browser deletion leading to the ThreadWithProgressWindow deletion.

In ThreadWithProgressWindow::runThread, it uses its member variable, so it read garbage leading to this crash.

I found a hack which do not allow button triggering while I’m still in the loading callback, but it’s not very clean
I tried having the browser deletion in a asyncupdater but it leads to the same issue.

Any ideas ?

Thanks,

Here is a callstack for a better understanding of the context

#0	0x00219e65 in m5v3::MachFiveFileBrowser::buttonClicked at MachFiveBrowser.cpp:594
#1	0x003cb052 in juce::ListenerList<juce::Button::Listener, juce::Array<juce::Button::Listener*, juce::DummyCriticalSection> >::callChecked<juce::Component::BailOutChecker, juce::Button*> at juce_ListenerList.h:181
#2	0x003703e9 in juce::Button::sendClickMessage at juce_Button.cpp:384
#3	0x003713ef in juce::Button::internalClickCallback at juce_Button.cpp:325
#4	0x0036fde5 in juce::Button::mouseUp at juce_Button.cpp:440
#5	0x0036ca6b in juce::Component::internalMouseUp at juce_Component.cpp:2450
#6	0x003ca786 in juce::MouseInputSourceInternal::sendMouseUp at juce_MouseInputSource.cpp:134
#7	0x003d1b94 in juce::MouseInputSourceInternal::setButtons at juce_MouseInputSource.cpp:166
#8	0x003d1e00 in juce::MouseInputSourceInternal::handleEvent at juce_MouseInputSource.cpp:283
#9	0x0037d962 in juce::MouseInputSource::handleEvent at juce_MouseInputSource.cpp:532
#10	0x0037da60 in juce::ComponentPeer::handleMouseEvent at juce_ComponentPeer.cpp:107
#11	0x003fe902 in juce::NSViewComponentPeer::sendMouseEvent at juce_mac_NSViewComponentPeer.mm:1455
#12	0x004025fd in juce::NSViewComponentPeer::redirectMouseUp at juce_mac_NSViewComponentPeer.mm:1467
#13	0x003fc913 in -[JuceNSView_1_54_19_SADebug asyncMouseUp:] at juce_mac_NSViewComponentPeer.mm:506
#14	0x90632711 in __NSThreadPerformPerform
#15	0x93ca445b in __CFRunLoopDoSources0
#16	0x93ca1f1f in __CFRunLoopRun
#17	0x93ca13f4 in CFRunLoopRunSpecific
#18	0x93ca1221 in CFRunLoopRunInMode
#19	0x003fbb22 in juce::MessageManager::runDispatchLoopUntil at juce_mac_MessageManager.mm:349
#20	0x00360df8 in juce::ModalComponentManager::runEventLoopForCurrentComponent at juce_ModalComponentManager.cpp:280
#21	0x00398fa6 in juce::Component::runModalLoop at juce_Component.cpp:1554
#22	0x00399054 in juce::ThreadWithProgressWindow::runThread at juce_ThreadWithProgressWindow.cpp:73
#23	0x00217d60 in m5v3::ProgramLoadingWorkerThread::LoadProgram at MachFiveBrowser.cpp:883
#24	0x00218363 in m5v3::MachFiveFileBrowser::loadprogram at MachFiveBrowser.cpp:711
#25	0x00219e2b in m5v3::MachFiveFileBrowser::pathActivated at MachFiveBrowser.cpp:687
#26	0x006af1c8 in uvi::FileBrowser::OnPathActivated at FileBrowser.cpp:619
#27	0x0089be14 in fastdelegate::FastDelegate1<uvi::Path const&, void>::operator() at FastDelegate.h:991
#28	0x006a7cdf in uvi::Signal1<uvi::Path const&, void>::operator() at SignalsSlots.h:251
#29	0x006a5175 in FileColumnViewItem::itemActivated at FileColumnView.cpp:160
#30	0x006a4136 in uvi::ColumnViewItem::itemDoubleClicked at ColumnView.h:41
#31	0x006a0b03 in ColumnViewContentColumn::listBoxItemDoubleClicked at ColumnView.cpp:200
#32	0x003a7ace in juce::ListBoxRowComponent::mouseDoubleClick at juce_ListBox.cpp:109
#33	0x0036cb91 in juce::Component::internalMouseUp at juce_Component.cpp:2466
#34	0x003ca786 in juce::MouseInputSourceInternal::sendMouseUp at juce_MouseInputSource.cpp:134
#35	0x003d1b94 in juce::MouseInputSourceInternal::setButtons at juce_MouseInputSource.cpp:166
#36	0x003d1e00 in juce::MouseInputSourceInternal::handleEvent at juce_MouseInputSource.cpp:283
#37	0x0037d962 in juce::MouseInputSource::handleEvent at juce_MouseInputSource.cpp:532
#38	0x0037da60 in juce::ComponentPeer::handleMouseEvent at juce_ComponentPeer.cpp:107
#39	0x003fe902 in juce::NSViewComponentPeer::sendMouseEvent at juce_mac_NSViewComponentPeer.mm:1455
#40	0x004025fd in juce::NSViewComponentPeer::redirectMouseUp at juce_mac_NSViewComponentPeer.mm:1467
#41	0x003fc913 in -[JuceNSView_1_54_19_SADebug asyncMouseUp:] at juce_mac_NSViewComponentPeer.mm:506
#42	0x90632711 in __NSThreadPerformPerform
#43	0x93ca445b in __CFRunLoopDoSources0
#44	0x93ca1f1f in __CFRunLoopRun
#45	0x93ca13f4 in CFRunLoopRunSpecific
#46	0x93ca1221 in CFRunLoopRunInMode
#47	0x90b01e04 in RunCurrentEventLoopInMode
#48	0x90b01af5 in ReceiveNextEventCommon
#49	0x90b01a3e in BlockUntilNextEventMatchingListInMode
#50	0x98c73595 in _DPSNextEvent
#51	0x98c72dd6 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
#52	0x98c351f3 in -[NSApplication run]
#53	0x003fb9a7 in juce::MessageManager::runDispatchLoop at juce_mac_MessageManager.mm:325
#54	0x002d67d2 in juce::JUCEApplication::main at juce_Application.cpp:240
#55	0x002d6937 in juce::JUCEApplication::main at juce_Application.cpp:282
#56	0x0041d613 in main at SAMain.cpp:98

#2

bump.


#3

Well, why are you calling runDispatchLoopUntil? It’s an inherently risky thing to do if there’s a chance that things could get deleted during the call…


#4

I’m not calling it, ThreadWithProgressWindow does and this is the problem.

check the callstack.

Thanks,


#5

I don’t understand then… Why would you allow your object to get deleted before runThread() returns, when there’s a chance it might be used at any point during the runThread call?


#6

There is two children in this component.

A modal ThreadWithProgressWindow and a close button which trigger the delete of this component (close button)

The problem is that the button can receive a triggering (buttonClicked in the callstack) while I’m still in the ThreadWithProgressWindow even if it’s supposed to be modal (ThreadWithProgressWindow::runThread in the callstack)

This happen if I click very quickly on the button while the progress window is about to be finished.

Hope this clarify things.


#7

Ah, I see! I thought that when you said “close button” you were talking about the cancel button in the ThreadWithProgressWindow box…

Ok - that’s a subtle and tricky one!

The neatest solution I can think of would be to use a temporary dummy modal component, which will take over when the thread window one goes away, e.g.

Component tempModalComponent; tempModalComponent.enterModalState(); myThread.runThread();

I guess I could actually add the same trick inside the ThreadWithProgressWindow::runThread() method, so the problem could never arise, but not sure if there may be other implications…


#8

Indeed, I don’t know if my case is tricky or if it should be handled by default in ThreadWithProgressWindow