Deadlock with XScopedLock


#1

Here it is:

(gdb) t 1
[Switching to thread 1 (Thread 4907)]#0  0x00007f60f827c7dd in nanosleep () at ../sysdeps/unix/syscall-template.S:82
82      ../sysdeps/unix/syscall-template.S: No such file or directory.
        in ../sysdeps/unix/syscall-template.S
(gdb) bt
#0  0x00007f60f827c7dd in nanosleep () at ../sysdeps/unix/syscall-template.S:82
#1  0x00000000006f2b7f in juce::Thread::sleep (millisecs=5) at ../../src/native/common/juce_posix_SharedCode.h:185
#2  0x00000000005ae8d7 in juce::Thread::waitForThreadToExit (this=0x7f60ec8ae5a0, timeOutMilliseconds=20000) at ../../src/threads/juce_Thread.cpp:162
#3  0x0000000000545001 in juce::MyComponent::unloadStuff (this=0x1a6df70) at ../../../Libraries/components/MyComponent.cpp:5423
#4  0x0000000000429ded in juce::LiveTab::buttonClicked (this=0x1a4fe80, buttonThatWasClicked=0x19fa980) at ../../components/LiveTab.cpp:626
#5  0x000000000042b2e7 in juce::LiveTab::handleCommandMessage (this=0x1a4fe80, commandId=8196) at ../../components/LiveTab.cpp:924
#6  0x000000000044eaea in juce::Tabber::perform (this=0x19dcfa0, info=...) at ../../components/Tabber.h:276
#7  0x00000000005b426a in juce::ApplicationCommandTarget::tryToInvoke (this=0x19dd080, info=..., async=false) at ../../src/application/juce_ApplicationCommandTarget.cpp:59
#8  0x00000000005b4682 in juce::ApplicationCommandTarget::invoke (this=0x19dd080, info=..., async=false) at ../../src/application/juce_ApplicationCommandTarget.cpp:140
#9  0x00000000005b2161 in juce::ApplicationCommandManager::invoke (this=0x19d75d0, info_=..., asynchronously=false) at ../../src/application/juce_ApplicationCommandManager.cpp:206
#10 0x00000000006a4a20 in juce::KeyPressMappingSet::invokeCommand (this=0x19d7640, commandID=8196, key=..., isKeyDown=true, millisecsSinceKeyPressed=0, originatingComponent=0x19d7ef0)
    at ../../src/gui/components/keyboard/juce_KeyPressMappingSet.cpp:228
#11 0x00000000006a55c9 in juce::KeyPressMappingSet::keyPressed (this=0x19d7640, key=..., originatingComponent=0x19d7ef0) at ../../src/gui/components/keyboard/juce_KeyPressMappingSet.cpp:349
#12 0x00000000006e495f in juce::ComponentPeer::handleKeyPress (this=0x19d86d0, keyCode=27, textCharacter=27 L'\033') at ../../src/gui/components/windows/juce_ComponentPeer.cpp:180
#13 0x000000000070425a in juce::LinuxComponentPeer::handleWindowMessage (this=0x19d86d0, event=0x7fffa8e13910) at ../../src/native/linux/juce_linux_Windowing.cpp:1343
#14 0x00000000006f91d0 in juce::juce_windowMessageReceive (event=0x7fffa8e13910) at ../../src/native/linux/juce_linux_Windowing.cpp:2768
#15 0x00000000006f7ab6 in juce_dispatchNextXEvent () at ../../src/native/linux/juce_linux_Messaging.cpp:416
#16 0x00000000006f7c3a in juce::juce_dispatchNextMessageOnSystemQueue (returnIfNoPendingMessages=false) at ../../src/native/linux/juce_linux_Messaging.cpp:473
#17 0x00000000005c6842 in juce::MessageManager::runDispatchLoopUntil (this=0x19a2d30, millisecondsToRunFor=-1) at ../../src/events/juce_MessageManager.cpp:160
#18 0x00000000005c672d in juce::MessageManager::runDispatchLoop (this=0x19a2d30) at ../../src/events/juce_MessageManager.cpp:137
#19 0x00000000005b021c in juce::JUCEApplication::main (commandLine=..., app=0x19a2230) at ../../src/application/juce_Application.cpp:171
#20 0x00000000005b0b0f in juce::JUCEApplication::main (argc=1, argv=0x7fffa8e13c48, newApp=0x19a2230) at ../../src/application/juce_Application.cpp:301
#21 0x0000000000464b30 in main (argc=1, argv=0x7fffa8e13c48) at ../../src/Main.cpp:290

(gdb) t 3     
[Switching to thread 3 (Thread 4915)]#0  pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162
162     ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: No such file or directory.
        in ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
(gdb) bt
#0  pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162
#1  0x00007f60f752f56d in ?? () from /usr/lib/libX11.so.6
#2  0x00007f60f752f217 in XLockDisplay () from /usr/lib/libX11.so.6
#3  0x00000000006f70d9 in ScopedXLock (this=0x7f60f0f42c8f) at ../../src/native/linux/juce_linux_Messaging.cpp:44
#4  0x0000000000709325 in juce::WindowedGLContext::swapBuffers (this=0x7f60ec006560) at ../../src/native/linux/juce_linux_Windowing.cpp:3378
#5  0x00000000006d9c3d in juce::OpenGLComponent::swapBuffers (this=0x7f60ec0061e0) at ../../src/gui/components/special/juce_OpenGLComponent.cpp:291

Seems like the X-lock is locked in the message thread, but only when pressing a shortcut key (not while clicking on a button with the mouse).
For me, the handleMessage in linux_Windowing.cpp:1343 should release the X lock when no more dealing with X stuff.

What do you think ?


#2

Thanks Cyril - yes, it should certainly release the lock before making the callback, it looks like that’s just an oversight. I’ll fix it right away…


#3

Thanks.


#4

Oh, found another one. Please have a look to line 1227 too, the keypress event also deadlock.
I’ve done this:

            case 2: // 'KeyPress'
            {
                char utf8 [64] = {0};
                KeySym sym;
                juce_wchar unicodeChar = String::fromUTF8 (utf8, sizeof (utf8) - 1) [0];
                int keyCode = (int) unicodeChar;
                bool keyDownChange = false;
                {
                    ScopedXLock xlock;
                    XKeyEvent* const keyEvent = (XKeyEvent*) &event->xkey;
                    updateKeyStates (keyEvent->keycode, true);


                    {
                        const char* oldLocale = ::setlocale (LC_ALL, 0);
                        ::setlocale (LC_ALL, "");
                        XLookupString (keyEvent, utf8, sizeof (utf8), &sym, 0);
                        ::setlocale (LC_ALL, oldLocale);
                    }

                    unicodeChar = String::fromUTF8 (utf8, sizeof (utf8) - 1) [0];
                    keyCode = (int) unicodeChar;

                    if (keyCode < 0x20)
                        keyCode = XKeycodeToKeysym (display, keyEvent->keycode, currentModifiers.isShiftDown() ? 1 : 0);


                    keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, true);
                }
                const ModifierKeys oldMods (currentModifiers);
                bool keyPressed = false;

#5

Gotcha. Thanks!