Easy fix
First, an easy fix:
(diff of src/main.c, between rev. 2584 and local)
Code: Select all
@@ -433,7 +433,7 @@
if (!redraw_pending && isActive) {
SDL_PushEvent(&event);
- redraw_pending = 1;
+ //redraw_pending = 1;
}
return(interval);
}
In the initial code, until it reaches line 853, every screen redraw event prevents new screen redraw events from pushed into the event queue.
But somehow (I'll explain it later), the event which locked out SDL_PushEvent() away disappears and fails to reach the line 853 sometimes, and in that case, SDL_PushEvent() becomes eternally unavailable to screen redraw events: means no more screen redraw.
Code: Select all
850 case SDL_USEREVENT:
851 if (event.user.code == 0 && isActive) {
852 on_redraw();
853 redraw_pending = 0;
854 }
Even though this fix does not "fix" disappearance of events and allows redundant screen redraw events to be fired, it seems to perform screen redraw.
Fix
Then forget the easy fix now, here comes a much "legitimate" fix:
(diff of src/main.c, between rev. 2584 and local)
Code: Select all
@@ -738,14 +738,16 @@
if (!strncmp(arg, "--no-debug", 10)) no_debug = TRUE;
}
- boot_lua(1, FALSE, argc, argv);
-
// initialize engine and set up resolution and depth
Uint32 flags=SDL_INIT_VIDEO | SDL_INIT_TIMER;
if (SDL_Init (flags) < 0) {
printf("cannot initialize SDL: %s\n", SDL_GetError ());
return -1;
}
+ // Filter events, to catch the quit event
+ SDL_SetEventFilter(event_filter);
+
+ boot_lua(1, FALSE, argc, argv);
SDL_WM_SetIcon(IMG_Load_RW(PHYSFSRWOPS_openRead("/engines/default/data/gfx/te4-icon.png"), TRUE), NULL);
@@ -794,9 +796,6 @@
pass_command_args(argc, argv);
- // Filter events, to catch the quit event
- SDL_SetEventFilter(event_filter);
-
SDL_Event event;
while (!exit_engine)
{
SDL_SetEventFilter(), when called, repeatedly calls SDL_PollEvent() internally to consume all events in the event queue and returns.
And while SDL_PollEvent() is repeatedly called, because the event queue is not locked during the whole operation of emptying the event queue (this is the bug, I think), new events are pushed to the event queue by other threads.
And sometimes, some of these newly pushed events happen to be a screen redraw event. Then, these screen redraw events will be consume by SDL_SetEventFilter()'s SDL_PollEvent(), not by our SDL_PollEvent().
Please note that, SDL uses realtime-base timers. They tick even if a debugger interrupted the process. So, if you repeat interrupt/continue in a debugger, there can be a sudden surge of event pushes because you spent SDL timers' interval while you were operating the debugger.
The solution is to execute SDL_SetEventFilter() much earlier, before any possible user-defined event firing mechanisms are initialized.
So that I moved SDL_SetEventFilter() before any of Lua boot functions (and also moved SDL_init() in favor of SDL_SetEventFilter()).
In this fix, redraw_pending can coexists: it means firing of redundant screen redraw events is suppressed.
Still, using a mutex/lock such as redraw_pending requires a clear picture of multithreading. Maybe applying above 2 fixes can be much safer than choosing only one of them.