emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 760107639b: Protect windows from garbage collection when a Client


From: Po Lu
Subject: master 760107639b: Protect windows from garbage collection when a ClientMessage is pending
Date: Sat, 16 Apr 2022 04:50:12 -0400 (EDT)

branch: master
commit 760107639be7657c4a209c9c04b17c79fc19f2c6
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Protect windows from garbage collection when a ClientMessage is pending
    
    * src/xterm.c (x_protect_window_for_callback)
    (x_unprotect_window_for_callback): New functions.
    (x_send_scroll_bar_event): Protect windows from garbage
    collection before sending event containing pointer to window.
    (handle_one_xevent): Unprotect after such a ClientMessage is
    received and the window put in the keyboard buffer.
    (x_term_init): Initialize protected windows list.
    (x_delete_display): Free that list.
    (mark_xterm): Mark the windows in that list.
    * src/xterm.h (struct x_display_info): New fields for recording
    a list of protected windows.
---
 src/xterm.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 src/xterm.h |  6 ++++++
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index c5b31553ae..ae3f2d7517 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -10846,6 +10846,35 @@ xt_horizontal_action_hook (Widget widget, XtPointer 
client_data, String action_n
 }
 #endif /* not USE_GTK */
 
+/* Protect WINDOW from garbage collection until a matching scroll bar
+   message is received.  Return whether or not protection
+   succeeded.  */
+static bool
+x_protect_window_for_callback (struct x_display_info *dpyinfo,
+                              Lisp_Object window)
+{
+  if (dpyinfo->n_protected_windows + 1
+      >= dpyinfo->protected_windows_max)
+    return false;
+
+  dpyinfo->protected_windows[dpyinfo->n_protected_windows++]
+    = window;
+  return true;
+}
+
+static void
+x_unprotect_window_for_callback (struct x_display_info *dpyinfo)
+{
+  if (!dpyinfo->n_protected_windows)
+    emacs_abort ();
+
+  dpyinfo->n_protected_windows--;
+
+  if (dpyinfo->n_protected_windows)
+    memmove (dpyinfo->protected_windows, &dpyinfo->protected_windows[1],
+            sizeof (Lisp_Object) * dpyinfo->n_protected_windows);
+}
+
 /* Send a client message with message type Xatom_Scrollbar for a
    scroll action to the frame of WINDOW.  PART is a value identifying
    the part of the scroll bar that was clicked on.  PORTION is the
@@ -10863,8 +10892,12 @@ x_send_scroll_bar_event (Lisp_Object window, enum 
scroll_bar_part part,
   verify (INTPTR_WIDTH <= 64);
   int sign_shift = INTPTR_WIDTH - 32;
 
-  block_input ();
+  /* Don't do anything if too many scroll bar events have been
+     sent but not received.  */
+  if (!x_protect_window_for_callback (FRAME_DISPLAY_INFO (f), window))
+    return;
 
+  block_input ();
   /* Construct a ClientMessage event to send to the frame.  */
   ev->type = ClientMessage;
   ev->message_type = (horizontal
@@ -18854,6 +18887,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       count++;
     }
 
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  if (event->xany.type == ClientMessage
+      && inev.ie.kind == SCROLL_BAR_CLICK_EVENT)
+    x_unprotect_window_for_callback (dpyinfo);
+#endif
+
   if (do_help
       && !(hold_quit && hold_quit->kind != NO_EVENT))
     {
@@ -23415,6 +23454,12 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
   x_extension_initialize (dpyinfo);
 #endif
 
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  dpyinfo->protected_windows = xmalloc (sizeof (Lisp_Object) * 256);
+  dpyinfo->n_protected_windows = 0;
+  dpyinfo->protected_windows_max = 256;
+#endif
+
   unblock_input ();
 
   return dpyinfo;
@@ -23469,12 +23514,14 @@ x_delete_display (struct x_display_info *dpyinfo)
   xfree (dpyinfo->x_id_name);
   xfree (dpyinfo->x_dnd_atoms);
   xfree (dpyinfo->color_cells);
-  xfree (dpyinfo);
-
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  xfree (dpyinfo->protected_windows);
+#endif
 #ifdef HAVE_XINPUT2
   if (dpyinfo->supports_xi2)
     x_free_xi_devices (dpyinfo);
 #endif
+  xfree (dpyinfo);
 }
 
 #ifdef USE_X_TOOLKIT
@@ -23817,11 +23864,17 @@ mark_xterm (void)
       mark_object (val);
     }
 
-#ifdef HAVE_XINPUT2
+#if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
     {
+#ifdef HAVE_XINPUT2
       for (i = 0; i < dpyinfo->num_devices; ++i)
        mark_object (dpyinfo->devices[i].name);
+#endif
+#ifdef USE_TOOLKIT_SCROLL_BARS
+      for (i = 0; i < dpyinfo->n_protected_windows; ++i)
+       mark_object (dpyinfo->protected_windows[i]);
+#endif
     }
 #endif
 }
diff --git a/src/xterm.h b/src/xterm.h
index a04596cdb1..5d2b397874 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -672,6 +672,12 @@ struct x_display_info
   int xshape_event_base;
   int xshape_error_base;
 #endif
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  Lisp_Object *protected_windows;
+  int n_protected_windows;
+  int protected_windows_max;
+#endif
 };
 
 #ifdef HAVE_X_I18N



reply via email to

[Prev in Thread] Current Thread [Next in Thread]