Repository navigation
Delay to close application after returning false from OnUserUpdate on Windows #312
Description
Hello, I was trying out the PGE in preparation for the game jam, and noticed that (at least on Windows) returning false from OnUserUpdate() didn't close the window until after some input/window event. After some digging, it seems that Host_Windows_WinAPI::systemActive is being updated to false, but because GetMessage() is blocking the event thread, the update is not seen until an event is received. I did a small modification to Host_Windows_WinAPI::StartSystem() that seems to address it. I'm not too sure about other hosts, but the one for X11 seems to do a hot polling loop which should avoid this issue, besides consuming a lot more CPU.
bool Host_Windows_WinAPI::StartSystem()
{
// Pre-context start hook
pPrimaryPGE->OnPreContextStart();
// Mark system as active
systemActive = true;
//##########################################################################
// This is the modified bit.
// Create system thread - handles gpu context
DWORD windowThreadId = GetCurrentThreadId();
std::thread threadSystem([this, windowThreadId]()
{
if(OnSystemThreadStart())
{
while(systemActive && OnSystemTick())
{
continue;
}
OnSystemThreadEnd();
}
// Update `systemActive` to false and post a WM_NULL message to make
// sure the blocking event loop below doesn't hang until an actual
// event arrives.
systemActive = false;
PostThreadMessage(windowThreadId, WM_NULL, 0, 0);
});
// Blocking event loop on this thread - handles windows. Note that we check
// whether the system is still active before calling GetMessage to make sure
// we don't miss updates to systemActive after DispatchMessage returns.
MSG msg;
while(systemActive && GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//##########################################################################
systemActive = false;
if(threadSystem.joinable())
threadSystem.join();
// Post-context end hook
return pPrimaryPGE->OnPostContextEnd();
}PS: On a slightly different subject, I was trying to figure out how input events are captured and sent to the system thread, and I could have missed something but it may be missing synchronization (at least on Windows, again)? Going back to to Host_Windows_WinAPI::StartSystem(), the call stack will look roughly like DispatchMessage() > WINAPI_EventHandler() > host->OnWindowEvent() > window->olc_OnXXX, and window state (mouse, keyboard, size, etc...) which is also accessed from the system thread is not being synchronized.
EDIT: So my modification did fix the issue but only partially. After some more testing, the window/event thread would hang indefinitely if the WM_QUIT message was posted while the window was being moved or resized, because it would be discarded by some modal loop. I did some more digging and it seems that posting a WM_QUIT is not quite the same as PostQuitMessage(), as the later would also set some flag to the thread's queue that would cause it to generate WM_QUIT events whenever it was empty, which should propagate all the way up. It isn't possible to call PostQuitMessage() from another thread tho, so I modified Host_Windows_WinAPI::StartSystem() again (above), but this time PostThreadMessage() is only used to wake up the event loop.
Activity
Johnnyg63 commentedon Oct 23, 2026
It was the onUserCreate() method that was having issues when False was returned, corrected in PR #342