VirtualBox

Opened 10 years ago

Last modified 9 years ago

#13494 new defect

Overloaded message loop makes Guest window unresponsive to inputs when guest additions installed

Reported by: Calmarius Owned by:
Component: guest additions Version: VirtualBox 4.3.16
Keywords: Cc:
Guest type: Windows Host type: Linux

Description

I'm on Ubuntu 12.04 host using LXDE desktop, and the guest is Windows XP. I haven't tested it with other Windows versions like win7.

My old GDI+ game completely freezes the guest window after some seconds. The only the to recover is simply killing the virtualbox process. It doesn't happen when guest additions are not installed.

I decided to investigate further and wrote the C program that reproduces the problem. (Simply using the Code::Blocks template with some edits).

The normal behavior is when you see the repeated rederawings clicking on the window should immediately bring up a messagebox with the coordinates. Or pressing key should bring up one with the character pressed. This happens on native windows, and in VirtualBox without guest additions.

With guest additions, if you run it for some time and click the window, nothing happens. The drawings keep going and you get response after several seconds.

It looks like the driver becomes overloaded with stuff, rendering the window unresponsive, till it processed all the events.

It's probably worth noting that the hard disk indicator is red when this hanging happen. Maybe it's writing somehing? I'm not sure whether the VM is thrashing or just because the whole GUI was frozen.

Adding several milliseconds of Sleep() into the message loop relieves the problem a bit. But it makes the game very laggy.

Hopefully this helps reproducing the problem.

Also a note: at least one OpenGL game the OpenArena works fine on VirtualBox too.

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif

#include <tchar.h>
#include <stdio.h>
#include <windows.h>

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("Code::Blocks Template Windows App"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop.*/
    for (;;)
    {
        /* Chew window messages. */
        while (PeekMessage(&messages, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&messages);
            DispatchMessage(&messages);
        }
        /* Step the game world. (omitted)*/

        /* Schedule redraw in next loop. */
        InvalidateRect(hwnd, NULL, TRUE);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;

    switch (message)                  /* handle the messages */
    {
        case WM_PAINT:
            BeginPaint(hwnd, &ps);
                /* Simulate expensive painting operation. */
                for (int i = 0; i < 1000; i++)
                {
                    MoveToEx(ps.hdc, rand() % 300, rand() % 300, NULL);
                    LineTo(ps.hdc, rand() % 300, rand() % 300);
                }
            EndPaint(hwnd, &ps);
        break;
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        case WM_LBUTTONDOWN:
            {
                WORD x = LOWORD(lParam);
                WORD y = HIWORD(lParam);
                TCHAR str[200];
                _sntprintf(str, 200, "%d: %d", x, y);
                MessageBox(hwnd, str, "", MB_OK);
            }
            break;
        case WM_CHAR:
            {
                TCHAR str[50];
                _sntprintf(str, 50, "%c\n", (char)wParam);
                MessageBox(hwnd, str, "", MB_OK);
            }
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

Attachments (1)

VBox.log (92.3 KB ) - added by Calmarius 10 years ago.

Download all attachments as: .zip

Change History (5)

comment:1 by sunlover, 10 years ago

Please attach VBox.log of the session where you run the test program and reproduced the long delay.

I tested it on Windows host with XP guest and it works fine, no delays.

by Calmarius, 10 years ago

Attachment: VBox.log added

comment:2 by Calmarius, 10 years ago

Attached the VBox.log.

It's indeed ok on the Windows host. I can reproduce it only on Linux hosts.

Last edited 10 years ago by Calmarius (previous) (diff)

comment:3 by Calmarius, 10 years ago

Disabling the "VirtualBox Graphics Adapter" device in the guest apparently gets rid of the delay.

comment:4 by Calmarius, 9 years ago

One important point I discovered: disabling the 2D acceleration seems to resolve the problem as well.

Note: See TracTickets for help on using tickets.

© 2023 Oracle
ContactPrivacy policyTerms of Use