mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-12 21:40:19 +00:00
quartz: Bug 674108 - Hard crash due to wrong NSAutoreleasePool stacking
Apply patch from Kristian Rietveld which addresses two issues in gdkeventloop-quartz.c: This patch moves the autorelease pool drain and introduces protection against the invalidated ufds. Basically, when we suspect ufds has been invalidated by a recursive main loop instance, we refrain from calling the collect function.
This commit is contained in:
parent
c8aa94f7a8
commit
79b3326eaa
@ -635,21 +635,6 @@ gdk_event_check (GSource *source)
|
||||
|
||||
GDK_THREADS_ENTER ();
|
||||
|
||||
/* Refresh the autorelease pool if we're at the base CFRunLoop level
|
||||
* (indicated by current_loop_level) and the base g_main_loop level
|
||||
* (indicated by g_main_depth()). Messing with the autorelease pool at
|
||||
* any level of nesting can cause access to deallocated memory because
|
||||
* autorelease_pool is static and releasing a pool will cause all pools
|
||||
* allocated inside of it to be released as well.
|
||||
*/
|
||||
if (current_loop_level == 0 && g_main_depth() == 0)
|
||||
{
|
||||
if (autorelease_pool)
|
||||
[autorelease_pool drain];
|
||||
|
||||
autorelease_pool = [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
|
||||
retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
|
||||
_gdk_quartz_event_loop_check_pending ());
|
||||
|
||||
@ -667,6 +652,21 @@ gdk_event_dispatch (GSource *source,
|
||||
|
||||
GDK_THREADS_ENTER ();
|
||||
|
||||
/* Refresh the autorelease pool if we're at the base CFRunLoop level
|
||||
* (indicated by current_loop_level) and the base g_main_loop level
|
||||
* (indicated by g_main_depth()). Messing with the autorelease pool at
|
||||
* any level of nesting can cause access to deallocated memory because
|
||||
* autorelease_pool is static and releasing a pool will cause all pools
|
||||
* allocated inside of it to be released as well.
|
||||
*/
|
||||
if (current_loop_level == 0 && g_main_depth() == 0)
|
||||
{
|
||||
if (autorelease_pool)
|
||||
[autorelease_pool drain];
|
||||
|
||||
autorelease_pool = [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
|
||||
_gdk_events_queue (_gdk_display);
|
||||
|
||||
event = _gdk_event_unqueue (_gdk_display);
|
||||
@ -704,6 +704,10 @@ poll_func (GPollFD *ufds,
|
||||
NSDate *limit_date;
|
||||
gint n_ready;
|
||||
|
||||
static GPollFD *last_ufds;
|
||||
|
||||
last_ufds = ufds;
|
||||
|
||||
n_ready = select_thread_start_poll (ufds, nfds, timeout_);
|
||||
if (n_ready > 0)
|
||||
timeout_ = 0;
|
||||
@ -722,7 +726,16 @@ poll_func (GPollFD *ufds,
|
||||
dequeue: YES];
|
||||
getting_events--;
|
||||
|
||||
if (n_ready < 0)
|
||||
/* We check if last_ufds did not change since the time this function was
|
||||
* called. It is possible that a recursive main loop (and thus recursive
|
||||
* invocation of this poll function) is triggered while in
|
||||
* nextEventMatchingMask:. If during that time new fds are added,
|
||||
* the cached fds array might be replaced in g_main_context_iterate().
|
||||
* So, we should avoid accessing the old fd array (still pointed at by
|
||||
* ufds) here in that case, since it might have been freed. We avoid this
|
||||
* by not calling the collect stage.
|
||||
*/
|
||||
if (last_ufds == ufds && n_ready < 0)
|
||||
n_ready = select_thread_collect_poll (ufds, nfds);
|
||||
|
||||
if (event &&
|
||||
|
Loading…
Reference in New Issue
Block a user