VirtualBox

Changeset 90057 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Jul 6, 2021 11:19:50 AM (4 years ago)
Author:
vboxsync
Message:

Additions: X11: seamless: prevent hang on shutdown (2), bugref:10032.

When X11 is no longer running, XCloseDisplay() call will indefinitely
hang on internal X11 mutex preventing service from shutdown. In this
commit, on shutdown code path, we examine if XOpenDisplay() returns non-NULL,
meaning that X server is still running, and only after this XCloseDisplay()
is called. In theory, this check still might not work (in case of bad timing),
but in general it improves sutuation and service is able to terminate smoothly.

In addition, before calling XNextEvent(), X11 monitor thread attempts to examine
with XPending() if there are some events actually pending. This is needed because
XNextEvent() might wait forever for the next event to arrive and block service
termination.

Location:
trunk/src/VBox/Additions/x11/VBoxClient
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp

    r89766 r90057  
    2424#include <iprt/assert.h>
    2525#include <iprt/vector.h>
     26#include <iprt/thread.h>
    2627#include <VBox/log.h>
    2728
     
    105106        stop();
    106107    mHostCallback = NULL;
    107     if (mDisplay)
    108         XCloseDisplay(mDisplay);
    109     mDisplay = NULL;
     108
     109    /* Before closing a Display, make sure X11 is still running. The indicator
     110     * that is when XOpenDisplay() returns non NULL. If it is not a
     111     * case, XCloseDisplay() will hang on internal X11 mutex forever. */
     112    Display *pDisplay = XOpenDisplay(NULL);
     113    if (pDisplay)
     114    {
     115        XCloseDisplay(pDisplay);
     116        if (mDisplay)
     117        {
     118            XCloseDisplay(mDisplay);
     119            mDisplay = NULL;
     120        }
     121    }
     122
    110123    if (mpRects)
    111124    {
     
    331344    }
    332345    mChanged = false;
    333     /* We execute this even when seamless is disabled, as it also waits for
    334      * enable and disable notification. */
    335     XNextEvent(mDisplay, &event);
     346
     347    if (XPending(mDisplay) > 0)
     348    {
     349        /* We execute this even when seamless is disabled, as it also waits for
     350         * enable and disable notification. */
     351        XNextEvent(mDisplay, &event);
     352    } else
     353    {
     354        /* This function is called in a loop by upper layer. In order to
     355         * prevent CPU spinning, sleep a bit before returning. */
     356        RTThreadSleep(300 /* ms */);
     357        return;
     358    }
     359
    336360    if (!mEnabled)
    337361        return;
     
    524548    if (pDisplay == NULL)
    525549    {
    526         VBClLogFatalError("Failed to open X11 display\n");
     550        VBClLogError("Failed to open X11 display\n");
    527551        return false;
    528552    }
  • trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp

    r86416 r90057  
    316316    event_return->xmap.window = g_SmlsEventWindow;
    317317    return True;
     318}
     319
     320/* Mock XNextEvent(): this also should not be needed. Just in case, always
     321 * return that at least one event is pending to be processed. */
     322extern "C" int XPending(Display *display);
     323int XPending(Display *display)
     324{
     325    RT_NOREF1(display);
     326    return 1;
    318327}
    319328
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette