Skip to content

Commit 33eb167

Browse files
committed
Fixed rare crash trying to interrupt SDL_WaitEvent()
Fixes #12797 (cherry picked from commit 992e4c5)
1 parent 4b4f6b3 commit 33eb167

File tree

7 files changed

+10
-47
lines changed

7 files changed

+10
-47
lines changed

src/events/SDL_events.c

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -738,21 +738,17 @@ static void SDL_CutEvent(SDL_EventEntry *entry)
738738

739739
static int SDL_SendWakeupEvent(void)
740740
{
741+
SDL_Window *wakeup_window;
741742
SDL_VideoDevice *_this = SDL_GetVideoDevice();
742743
if (_this == NULL || !_this->SendWakeupEvent) {
743744
return 0;
744745
}
745746

746-
SDL_LockMutex(_this->wakeup_lock);
747-
{
748-
if (_this->wakeup_window) {
749-
_this->SendWakeupEvent(_this, _this->wakeup_window);
750-
751-
/* No more wakeup events needed until we enter a new wait */
752-
_this->wakeup_window = NULL;
753-
}
747+
/* We only want to do this once while waiting for an event, so set it to NULL atomically here */
748+
wakeup_window = (SDL_Window *)SDL_AtomicSetPtr(&_this->wakeup_window, NULL);
749+
if (wakeup_window) {
750+
_this->SendWakeupEvent(_this, wakeup_window);
754751
}
755-
SDL_UnlockMutex(_this->wakeup_lock);
756752

757753
return 0;
758754
}
@@ -1009,18 +1005,7 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
10091005
int status;
10101006
SDL_PumpEventsInternal(SDL_TRUE);
10111007

1012-
SDL_LockMutex(_this->wakeup_lock);
1013-
{
1014-
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
1015-
/* If status == 0 we are going to block so wakeup will be needed. */
1016-
if (status == 0) {
1017-
_this->wakeup_window = wakeup_window;
1018-
} else {
1019-
_this->wakeup_window = NULL;
1020-
}
1021-
}
1022-
SDL_UnlockMutex(_this->wakeup_lock);
1023-
1008+
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
10241009
if (status < 0) {
10251010
/* Got an error: return */
10261011
break;
@@ -1033,8 +1018,6 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
10331018
if (timeout > 0) {
10341019
Uint32 elapsed = SDL_GetTicks() - start;
10351020
if (elapsed >= (Uint32)timeout) {
1036-
/* Set wakeup_window to NULL without holding the lock. */
1037-
_this->wakeup_window = NULL;
10381021
return 0;
10391022
}
10401023
loop_timeout = (int)((Uint32)timeout - elapsed);
@@ -1049,9 +1032,9 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
10491032
}
10501033
}
10511034

1035+
SDL_AtomicSetPtr(&_this->wakeup_window, wakeup_window);
10521036
status = _this->WaitEventTimeout(_this, loop_timeout);
1053-
/* Set wakeup_window to NULL without holding the lock. */
1054-
_this->wakeup_window = NULL;
1037+
SDL_AtomicSetPtr(&_this->wakeup_window, NULL);
10551038
if (status == 0 && poll_interval != SDL_MAX_SINT16 && loop_timeout == poll_interval) {
10561039
/* We may have woken up to poll. Try again */
10571040
continue;

src/video/SDL_sysvideo.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,7 @@ struct SDL_VideoDevice
355355
SDL_bool checked_texture_framebuffer;
356356
SDL_bool is_dummy;
357357
SDL_bool suspend_screensaver;
358-
SDL_Window *wakeup_window;
359-
SDL_mutex *wakeup_lock; /* Initialized only if WaitEventTimeout/SendWakeupEvent are supported */
358+
void *wakeup_window;
360359
int num_displays;
361360
SDL_VideoDisplay *displays;
362361
SDL_Window *windows;

src/video/SDL_video.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3368,9 +3368,7 @@ void SDL_DestroyWindow(SDL_Window *window)
33683368
_this->current_glwin = NULL;
33693369
}
33703370

3371-
if (_this->wakeup_window == window) {
3372-
_this->wakeup_window = NULL;
3373-
}
3371+
SDL_AtomicCASPtr(&_this->wakeup_window, window, NULL);
33743372

33753373
/* Now invalidate magic */
33763374
window->magic = NULL;

src/video/cocoa/SDL_cocoavideo.m

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ @implementation SDL_VideoData
4848
static void Cocoa_DeleteDevice(SDL_VideoDevice * device)
4949
{ @autoreleasepool
5050
{
51-
if (device->wakeup_lock) {
52-
SDL_DestroyMutex(device->wakeup_lock);
53-
}
5451
CFBridgingRelease(device->driverdata);
5552
SDL_free(device);
5653
}}
@@ -76,7 +73,6 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice * device)
7673
return NULL;
7774
}
7875
device->driverdata = (void *)CFBridgingRetain(data);
79-
device->wakeup_lock = SDL_CreateMutex();
8076

8177
/* Set the function pointers */
8278
device->VideoInit = Cocoa_VideoInit;

src/video/wayland/SDL_waylandvideo.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,6 @@ static void Wayland_DeleteDevice(SDL_VideoDevice *device)
162162
WAYLAND_wl_display_flush(data->display);
163163
WAYLAND_wl_display_disconnect(data->display);
164164
}
165-
if (device->wakeup_lock) {
166-
SDL_DestroyMutex(device->wakeup_lock);
167-
}
168165
SDL_free(data);
169166
SDL_free(device);
170167
SDL_WAYLAND_UnloadSymbols();
@@ -233,7 +230,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
233230
}
234231

235232
device->driverdata = data;
236-
device->wakeup_lock = SDL_CreateMutex();
237233

238234
/* Set the function pointers */
239235
device->VideoInit = Wayland_VideoInit;

src/video/windows/SDL_windowsvideo.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@ static void WIN_DeleteDevice(SDL_VideoDevice *device)
9393
SDL_UnloadObject(data->shcoreDLL);
9494
}
9595
#endif
96-
if (device->wakeup_lock) {
97-
SDL_DestroyMutex(device->wakeup_lock);
98-
}
9996
SDL_free(device->driverdata);
10097
SDL_free(device);
10198
}
@@ -120,7 +117,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
120117
return NULL;
121118
}
122119
device->driverdata = data;
123-
device->wakeup_lock = SDL_CreateMutex();
124120

125121
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
126122
data->userDLL = SDL_LoadObject("USER32.DLL");

src/video/x11/SDL_x11video.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,6 @@ static void X11_DeleteDevice(SDL_VideoDevice *device)
108108
X11_XCloseDisplay(data->request_display);
109109
}
110110
SDL_free(data->windowlist);
111-
if (device->wakeup_lock) {
112-
SDL_DestroyMutex(device->wakeup_lock);
113-
}
114111
SDL_free(device->driverdata);
115112
SDL_free(device);
116113

@@ -204,8 +201,6 @@ static SDL_VideoDevice *X11_CreateDevice(void)
204201
return NULL;
205202
}
206203

207-
device->wakeup_lock = SDL_CreateMutex();
208-
209204
#ifdef X11_DEBUG
210205
X11_XSynchronize(data->display, True);
211206
#endif

0 commit comments

Comments
 (0)