--- a/gtk+-3.6.4/gdk/quartz/gdkeventloop-quartz.c	Mon Nov 19 17:32:20 2012
+++ b/gtk+-3.6.4/gdk/quartz/gdkeventloop-quartz.c	Tue Jul 09 23:59:14 2013
@@ -168,6 +168,12 @@
 static GPollFD *current_pollfds;
 static guint current_n_pollfds;
 
+/* We maintain serial numbers for calls to the start function. Because we
+ * only test for equality of this number (and not smaller/greater than)
+ * no special handling is needed for wrap around.
+ */
+static guint select_thread_start_serial = 0;
+
 /* These are the file descriptors that the select thread should pick
  * up and start polling when it has a chance.
  */
@@ -399,6 +405,8 @@
   gint poll_fd_index = -1;
   gint i;
 
+  select_thread_start_serial++;
+
   for (i = 0; i < nfds; i++)
     if (ufds[i].fd == -1)
       {
@@ -620,6 +628,31 @@
   
   *timeout = -1;
 
+  /* The prepare stage is the stage before the main loop starts polling
+   * and dispatching events. The autorelease poll is drained here for
+   * the preceding main loop iteration or, in case of the first iteration,
+   * for the operations carried out between event loop initialization and
+   * this first iteration.
+   *
+   * The autorelease poll must only be drained when the following conditions
+   * apply:
+   *  - We are at the base CFRunLoop level (indicated by current_loop_level),
+   *  - We are at the base g_main_loop level (indicated by
+   *    g_main_depth())
+   *  - We are at the base poll_func level (indicated by getting events).
+   *
+   * 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 && getting_events == 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 ());
 
@@ -652,21 +685,6 @@
 
   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_quartz_display_queue_events (_gdk_display);
 
   event = _gdk_event_unqueue (_gdk_display);
@@ -702,15 +720,33 @@
   NSEvent *event;
   NSDate *limit_date;
   gint n_ready;
+  guint current_select_thread_serial;
 
-  static GPollFD *last_ufds;
+  /* Maintain current poll parameters as static parameters. On recursive
+   * calls to poll, we update the values. This way, if the poll array
+   * is updated in an recursive call, we can still access the new array
+   * when the recursion is wound down.
+   *
+   * The ufds value that is pushed in is allocated in g_main_context_iterate()
+   * and is only reallocated for enlargement of this array. The array thus
+   * never shrinks.
+   */
+  static GPollFD *current_ufds = NULL;
+  static int current_nfds = 0;
 
-  last_ufds = ufds;
+  current_ufds = ufds;
+  current_nfds = nfds;
 
   n_ready = select_thread_start_poll (ufds, nfds, timeout_);
   if (n_ready > 0)
     timeout_ = 0;
 
+  /* Using this serial number, we can check below whether the select
+   * thread was started/collected in a recursive invocation of this
+   * function.
+   */
+  current_select_thread_serial = select_thread_start_serial;
+
   if (timeout_ == -1)
     limit_date = [NSDate distantFuture];
   else if (timeout_ == 0)
@@ -725,17 +761,31 @@
                                dequeue: YES];
   getting_events--;
 
-  /* 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);
+  /* Note that, from this point onwards, ufds might point to freed memory! */
+
+  if (current_select_thread_serial == select_thread_start_serial)
+    {
+      if (n_ready < 0)
+        n_ready = select_thread_collect_poll (current_ufds, nfds);
+
+      /* Nothing should be done in case no poll func recursion occurred
+       * and n_ready > 0.
+       */
+    }
+  else
+    {
+      /* In this case, a recursive invocation of the poll function has
+       * collected results from the select thread. We clear the ufds
+       * values so that stale poll results are not returned. In case
+       * we did not receive results from start poll above, we also
+       * set n_ready to zero.
+       */
+      int i;
+
+      n_ready = 0;
+      for (i = 0; i < nfds; i++)
+        current_ufds[i].revents = 0;
+    }
       
   if (event &&
       [event type] == NSApplicationDefined &&
@@ -889,7 +939,7 @@
     }
   else if (timeout > 0)
     {
-      /* We need to get the run loop to break out of its wait when our timeout
+      /* We need to get the run loop to break out of it's wait when our timeout
        * expires. We do this by adding a dummy timer that we'll remove immediately
        * after the wait wakes up.
        */
