Skip to content

Commit 992e4c5

Browse files
committed
Fixed rare crash trying to interrupt SDL_WaitEvent()
Fixes #12797
1 parent 4db8fe2 commit 992e4c5

File tree

7 files changed

+9
-47
lines changed

7 files changed

+9
-47
lines changed

src/events/SDL_events.c

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,16 +1102,11 @@ static void SDL_SendWakeupEvent(void)
11021102
return;
11031103
}
11041104

1105-
SDL_LockMutex(_this->wakeup_lock);
1106-
{
1107-
if (_this->wakeup_window) {
1108-
_this->SendWakeupEvent(_this, _this->wakeup_window);
1109-
1110-
// No more wakeup events needed until we enter a new wait
1111-
_this->wakeup_window = NULL;
1112-
}
1105+
// We only want to do this once while waiting for an event, so set it to NULL atomically here
1106+
SDL_Window *wakeup_window = (SDL_Window *)SDL_SetAtomicPointer(&_this->wakeup_window, NULL);
1107+
if (wakeup_window) {
1108+
_this->SendWakeupEvent(_this, wakeup_window);
11131109
}
1114-
SDL_UnlockMutex(_this->wakeup_lock);
11151110
#endif
11161111
}
11171112

@@ -1549,18 +1544,7 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu
15491544
*/
15501545
SDL_PumpEventsInternal(true);
15511546

1552-
SDL_LockMutex(_this->wakeup_lock);
1553-
{
1554-
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
1555-
// If status == 0 we are going to block so wakeup will be needed.
1556-
if (status == 0) {
1557-
_this->wakeup_window = wakeup_window;
1558-
} else {
1559-
_this->wakeup_window = NULL;
1560-
}
1561-
}
1562-
SDL_UnlockMutex(_this->wakeup_lock);
1563-
1547+
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
15641548
if (status < 0) {
15651549
// Got an error: return
15661550
break;
@@ -1573,8 +1557,6 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu
15731557
if (timeoutNS > 0) {
15741558
Sint64 elapsed = SDL_GetTicksNS() - start;
15751559
if (elapsed >= timeoutNS) {
1576-
// Set wakeup_window to NULL without holding the lock.
1577-
_this->wakeup_window = NULL;
15781560
return 0;
15791561
}
15801562
loop_timeoutNS = (timeoutNS - elapsed);
@@ -1587,9 +1569,9 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu
15871569
loop_timeoutNS = poll_intervalNS;
15881570
}
15891571
}
1572+
SDL_SetAtomicPointer(&_this->wakeup_window, wakeup_window);
15901573
status = _this->WaitEventTimeout(_this, loop_timeoutNS);
1591-
// Set wakeup_window to NULL without holding the lock.
1592-
_this->wakeup_window = NULL;
1574+
SDL_SetAtomicPointer(&_this->wakeup_window, NULL);
15931575
if (status == 0 && poll_intervalNS != SDL_MAX_SINT64 && loop_timeoutNS == poll_intervalNS) {
15941576
// We may have woken up to poll. Try again
15951577
continue;

src/video/SDL_sysvideo.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,7 @@ struct SDL_VideoDevice
405405
bool checked_texture_framebuffer;
406406
bool is_dummy;
407407
bool suspend_screensaver;
408-
SDL_Window *wakeup_window;
409-
SDL_Mutex *wakeup_lock; // Initialized only if WaitEventTimeout/SendWakeupEvent are supported
408+
void *wakeup_window;
410409
int num_displays;
411410
SDL_VideoDisplay **displays;
412411
SDL_Rect desktop_bounds;

src/video/SDL_video.c

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

4396-
if (_this->wakeup_window == window) {
4397-
_this->wakeup_window = NULL;
4398-
}
4396+
SDL_CompareAndSwapAtomicPointer(&_this->wakeup_window, window, NULL);
43994397

44004398
// Now invalidate magic
44014399
SDL_SetObjectValid(window, SDL_OBJECT_TYPE_WINDOW, false);

src/video/cocoa/SDL_cocoavideo.m

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ @implementation SDL_CocoaVideoData
4949
static void Cocoa_DeleteDevice(SDL_VideoDevice *device)
5050
{
5151
@autoreleasepool {
52-
if (device->wakeup_lock) {
53-
SDL_DestroyMutex(device->wakeup_lock);
54-
}
5552
CFBridgingRelease(device->internal);
5653
SDL_free(device);
5754
}
@@ -81,7 +78,6 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device)
8178
return NULL;
8279
}
8380
device->internal = (SDL_VideoData *)CFBridgingRetain(data);
84-
device->wakeup_lock = SDL_CreateMutex();
8581
device->system_theme = Cocoa_GetSystemTheme();
8682

8783
// Set the function pointers

src/video/wayland/SDL_waylandvideo.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,6 @@ static void Wayland_DeleteDevice(SDL_VideoDevice *device)
447447
WAYLAND_wl_display_disconnect(data->display);
448448
SDL_ClearProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER);
449449
}
450-
if (device->wakeup_lock) {
451-
SDL_DestroyMutex(device->wakeup_lock);
452-
}
453450
SDL_free(data);
454451
SDL_free(device);
455452
SDL_WAYLAND_UnloadSymbols();
@@ -576,7 +573,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
576573
}
577574

578575
device->internal = data;
579-
device->wakeup_lock = SDL_CreateMutex();
580576

581577
// Set the function pointers
582578
device->VideoInit = Wayland_VideoInit;

src/video/windows/SDL_windowsvideo.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,6 @@ static void WIN_DeleteDevice(SDL_VideoDevice *device)
124124
SDL_UnloadObject(data->dxgiDLL);
125125
}
126126
#endif
127-
if (device->wakeup_lock) {
128-
SDL_DestroyMutex(device->wakeup_lock);
129-
}
130127
SDL_free(device->internal->rawinput);
131128
SDL_free(device->internal);
132129
SDL_free(device);
@@ -152,7 +149,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
152149
return NULL;
153150
}
154151
device->internal = data;
155-
device->wakeup_lock = SDL_CreateMutex();
156152
device->system_theme = WIN_GetSystemTheme();
157153

158154
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)

src/video/x11/SDL_x11video.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ static void X11_DeleteDevice(SDL_VideoDevice *device)
6565
X11_XCloseDisplay(data->request_display);
6666
}
6767
SDL_free(data->windowlist);
68-
if (device->wakeup_lock) {
69-
SDL_DestroyMutex(device->wakeup_lock);
70-
}
7168
SDL_free(device->internal);
7269
SDL_free(device);
7370

@@ -148,8 +145,6 @@ static SDL_VideoDevice *X11_CreateDevice(void)
148145
return NULL;
149146
}
150147

151-
device->wakeup_lock = SDL_CreateMutex();
152-
153148
#ifdef X11_DEBUG
154149
X11_XSynchronize(data->display, True);
155150
#endif

0 commit comments

Comments
 (0)