emacs-diffs
[Top][All Lists]
Advanced

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

master 6f940c6a118: Plug various leaks and fix input method initializati


From: Po Lu
Subject: master 6f940c6a118: Plug various leaks and fix input method initialization
Date: Sun, 21 May 2023 23:54:18 -0400 (EDT)

branch: master
commit 6f940c6a1183dd1660f35e6c82d33183a6892cb4
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Plug various leaks and fix input method initialization
    
    * src/image.c (free_bitmap_record): Free bm->name correctly even
    if the display connection has been closed.
    * src/xfns.c (x_window): Use dpyinfo-specific `use_xim' flag.
    * src/xterm.c (use_xim): Remove global variable.
    (xim_destroy_callback): Free `xim_styles' if present, and set it
    to NULL to be on the safe side.
    (xim_open_dpy): Consult dpyinfo->use_xim instead.  Don't leak
    `xim_styles' if an IM was previously opened.
    (xim_initialize): Use dpyinfo-specific `use_xim' flag.
    (xim_close_dpy): Check if `dpyinfo->xim_callback_data' is set
    before unregistering the instantiation callback.
    (x_term_init): Determine whether or not to use XIM for each
    display opened, instead of using the resources of the last
    display opened to toggle a global flag.
    (x_delete_terminal): Always call `image_destroy_all_bitmaps' and
    `xim_close_dpy'.  Free storage used to hold bitmap records.
    * src/xterm.h (struct x_display_info): New field `use_xim'.
---
 src/image.c |  14 ++++--
 src/xfns.c  |  56 +++++++++++-----------
 src/xterm.c | 156 ++++++++++++++++++++++++++++++++++++++++--------------------
 src/xterm.h |  11 ++---
 4 files changed, 148 insertions(+), 89 deletions(-)

diff --git a/src/image.c b/src/image.c
index 87a0c1ca497..c9420b48f4a 100644
--- a/src/image.c
+++ b/src/image.c
@@ -842,9 +842,17 @@ static void
 free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
 {
 #ifdef HAVE_X_WINDOWS
-  XFreePixmap (dpyinfo->display, bm->pixmap);
-  if (bm->have_mask)
-    XFreePixmap (dpyinfo->display, bm->mask);
+  /* Free the pixmap and mask.  Only do this if DPYINFO->display is
+     still set, which may not be the case if the connection has
+     already been closed in response to an IO error.  */
+
+  if (dpyinfo->display)
+    {
+      XFreePixmap (dpyinfo->display, bm->pixmap);
+      if (bm->have_mask)
+       XFreePixmap (dpyinfo->display, bm->mask);
+    }
+
 #ifdef USE_CAIRO
   if (bm->stipple)
     cairo_pattern_destroy (bm->stipple);
diff --git a/src/xfns.c b/src/xfns.c
index 9e004f6a678..234a48c908f 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4252,9 +4252,9 @@ x_window (struct frame *f, long window_prompting)
 
 #ifdef HAVE_X_I18N
   FRAME_XIC (f) = NULL;
-  if (use_xim)
+  if (FRAME_DISPLAY_INFO (f)->use_xim)
     create_frame_xic (f);
-#endif
+#endif /* HAVE_X_I18N */
 
   f->output_data.x->wm_hints.input = True;
   f->output_data.x->wm_hints.flags |= InputHint;
@@ -4355,32 +4355,32 @@ x_window (struct frame *f)
 
 #ifdef HAVE_X_I18N
   FRAME_XIC (f) = NULL;
-  if (use_xim)
-  {
-    block_input ();
-    create_frame_xic (f);
-    if (FRAME_XIC (f))
-      {
-       /* XIM server might require some X events. */
-       unsigned long fevent = NoEventMask;
-       XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+  if (FRAME_DISPLAY_INFO (f)->use_xim)
+    {
+      block_input ();
+      create_frame_xic (f);
+      if (FRAME_XIC (f))
+       {
+         /* XIM server might require some X events. */
+         unsigned long fevent = NoEventMask;
+         XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
 
-       if (fevent != NoEventMask)
-         {
-           XSetWindowAttributes attributes;
-           XWindowAttributes wattr;
-           unsigned long attribute_mask;
-
-           XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                                 &wattr);
-           attributes.event_mask = wattr.your_event_mask | fevent;
-           attribute_mask = CWEventMask;
-           XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                                    attribute_mask, &attributes);
-         }
-      }
-    unblock_input ();
-  }
+         if (fevent != NoEventMask)
+           {
+             XSetWindowAttributes attributes;
+             XWindowAttributes wattr;
+             unsigned long attribute_mask;
+
+             XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                                   &wattr);
+             attributes.event_mask = wattr.your_event_mask | fevent;
+             attribute_mask = CWEventMask;
+             XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                                      attribute_mask, &attributes);
+           }
+       }
+      unblock_input ();
+    }
 #endif
 
   append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
@@ -4427,7 +4427,7 @@ x_window (struct frame *f)
   initial_set_up_x_back_buffer (f);
 
 #ifdef HAVE_X_I18N
-  if (use_xim)
+  if (FRAME_DISPLAY_INFO (f)->use_xim)
     {
       create_frame_xic (f);
       if (FRAME_XIC (f))
diff --git a/src/xterm.c b/src/xterm.c
index 15bd9f98d17..0450230efe6 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -798,13 +798,6 @@ typedef int (*Emacs_XIOErrorHandler) (Display *);
 #define USE_CAIRO_XCB_SURFACE
 #endif
 
-/* Default to using XIM if available.  */
-#ifdef USE_XIM
-bool use_xim = true;
-#else
-bool use_xim = false;  /* configure --without-xim */
-#endif
-
 #if XCB_SHAPE_MAJOR_VERSION > 1              \
   || (XCB_SHAPE_MAJOR_VERSION == 1 && \
       XCB_SHAPE_MINOR_VERSION >= 1)
@@ -26666,7 +26659,12 @@ xim_destroy_callback (XIM xim, XPointer client_data, 
XPointer call_data)
 
   /* No need to call XCloseIM.  */
   dpyinfo->xim = NULL;
-  XFree (dpyinfo->xim_styles);
+
+  /* Also free IM values; those are allocated separately upon
+     XGetIMValues.  */
+  if (dpyinfo->xim_styles)
+    XFree (dpyinfo->xim_styles);
+  dpyinfo->xim_styles = NULL;
   unblock_input ();
 }
 
@@ -26684,10 +26682,20 @@ xim_open_dpy (struct x_display_info *dpyinfo, char 
*resource_name)
   XIM xim;
   const char *locale;
 
-  if (use_xim)
+  if (dpyinfo->use_xim)
     {
       if (dpyinfo->xim)
-       XCloseIM (dpyinfo->xim);
+       {
+         XCloseIM (dpyinfo->xim);
+
+         /* Free values left over from the last time the IM
+            connection was established.  */
+
+         if (dpyinfo->xim_styles)
+           XFree (dpyinfo->xim_styles);
+         dpyinfo->xim_styles = NULL;
+       }
+
       xim = XOpenIM (dpyinfo->display, dpyinfo->rdb, resource_name,
                     emacs_class);
       dpyinfo->xim = xim;
@@ -26716,7 +26724,6 @@ xim_open_dpy (struct x_display_info *dpyinfo, char 
*resource_name)
                                            build_string (locale));
        }
     }
-
   else
 #endif /* HAVE_XIM */
     dpyinfo->xim = NULL;
@@ -26785,7 +26792,7 @@ xim_initialize (struct x_display_info *dpyinfo, char 
*resource_name)
 {
   dpyinfo->xim = NULL;
 #ifdef HAVE_XIM
-  if (use_xim)
+  if (dpyinfo->use_xim)
     {
 #ifdef HAVE_X11R6_XIM
       struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
@@ -26794,15 +26801,19 @@ xim_initialize (struct x_display_info *dpyinfo, char 
*resource_name)
       dpyinfo->xim_callback_data = xim_inst;
       xim_inst->dpyinfo = dpyinfo;
       xim_inst->resource_name = xstrdup (resource_name);
-      ret = XRegisterIMInstantiateCallback
-       (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name,
-        emacs_class, xim_instantiate_callback,
-        /* This is XPointer in XFree86 but (XPointer *) on Tru64, at
-           least, but the configure test doesn't work because
-           xim_instantiate_callback can either be XIMProc or
-           XIDProc, so just cast to void *.  */
-        (void *) xim_inst);
-      eassert (ret == True);
+
+      /* The last argument is XPointer in XFree86 but (XPointer *) on
+        Tru64, at least, but the configure test doesn't work because
+        xim_instantiate_callback can either be XIMProc or XIDProc, so
+        just cast to void *.  */
+
+      ret = XRegisterIMInstantiateCallback (dpyinfo->display,
+                                           dpyinfo->rdb,
+                                           xim_inst->resource_name,
+                                           emacs_class,
+                                           xim_instantiate_callback,
+                                           (void *) xim_inst);
+      eassert (ret);
 #else /* not HAVE_X11R6_XIM */
       xim_open_dpy (dpyinfo, resource_name);
 #endif /* not HAVE_X11R6_XIM */
@@ -26811,32 +26822,56 @@ xim_initialize (struct x_display_info *dpyinfo, char 
*resource_name)
 }
 
 
-/* Close the connection to the XIM server on display DPYINFO. */
+/* Close the connection to the XIM server on display DPYINFO.
+   Unregister any IM instantiation callback previously installed,
+   close the connection to the IM server if possible, and free any
+   retrieved IM values.  */
 
 static void
 xim_close_dpy (struct x_display_info *dpyinfo)
 {
 #ifdef HAVE_XIM
-  if (use_xim)
-    {
 #ifdef HAVE_X11R6_XIM
-      struct xim_inst_t *xim_inst = dpyinfo->xim_callback_data;
+  struct xim_inst_t *xim_inst;
+  Bool rc;
+
+  /* If dpyinfo->xim_callback_data is not set, then IM support wasn't
+     initialized, which can happen if Xlib doesn't understand the C
+     locale being used.  */
+
+  if (dpyinfo->xim_callback_data)
+    {
+      xim_inst = dpyinfo->xim_callback_data;
 
       if (dpyinfo->display)
        {
-         Bool ret = XUnregisterIMInstantiateCallback
-           (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name,
-            emacs_class, xim_instantiate_callback, (void *) xim_inst);
-         eassert (ret == True);
+         rc = XUnregisterIMInstantiateCallback (dpyinfo->display,
+                                                dpyinfo->rdb,
+                                                xim_inst->resource_name,
+                                                emacs_class,
+                                                xim_instantiate_callback,
+                                                (void *) xim_inst);
+         eassert (rc);
        }
+
       xfree (xim_inst->resource_name);
       xfree (xim_inst);
-#endif /* HAVE_X11R6_XIM */
-      if (dpyinfo->display)
-       XCloseIM (dpyinfo->xim);
-      dpyinfo->xim = NULL;
-      XFree (dpyinfo->xim_styles);
     }
+#endif /* HAVE_X11R6_XIM */
+
+  /* Now close the connection to the input method server.  This may
+     access the display connection, and isn't safe if the display has
+     already been closed.  */
+
+  if (dpyinfo->display && dpyinfo->xim)
+    XCloseIM (dpyinfo->xim);
+  dpyinfo->xim = NULL;
+
+  /* Free the list of XIM styles retrieved.  */
+
+  if (dpyinfo->xim_styles)
+    XFree (dpyinfo->xim_styles);
+  dpyinfo->xim_styles = NULL;
 #endif /* HAVE_XIM */
 }
 
@@ -30766,14 +30801,6 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
   dpyinfo->fixes_pointer_blanking = (egetenv ("EMACS_XFIXES") != NULL);
 #endif
 
-#ifdef HAVE_X_I18N
-  /* Avoid initializing input methods if the X library does not
-     support Emacs's locale.  When the current locale is not
-     supported, decoding input method strings becomes undefined.  */
-  if (XSupportsLocale ())
-    xim_initialize (dpyinfo, resource_name);
-#endif
-
   xsettings_initialize (dpyinfo);
 
   /* This is only needed for distinguishing keyboard and process input.  */
@@ -30832,25 +30859,33 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
       XSynchronize (dpyinfo->display, True);
   }
 
+#ifdef HAVE_X_I18N
   {
     AUTO_STRING (useXIM, "useXIM");
     AUTO_STRING (UseXIM, "UseXIM");
     Lisp_Object value = gui_display_get_resource (dpyinfo, useXIM, UseXIM,
                                                   Qnil, Qnil);
+
+    /* `USE_XIM' controls whether Emacs should use X input methods by
+       default, not whether or not XIM is available.  */
+
 #ifdef USE_XIM
+    dpyinfo->use_xim = true;
+
     if (STRINGP (value)
        && (!strcmp (SSDATA (value), "false")
            || !strcmp (SSDATA (value), "off")))
-      use_xim = false;
-#else
+      dpyinfo->use_xim = false;
+#else /* !USE_XIM */
+    dpyinfo->use_xim = false;
+
     if (STRINGP (value)
        && (!strcmp (SSDATA (value), "true")
            || !strcmp (SSDATA (value), "on")))
-      use_xim = true;
-#endif
+      dpyinfo->use_xim = true;
+#endif /* USE_XIM */
   }
 
-#ifdef HAVE_X_I18N
   {
     AUTO_STRING (inputStyle, "inputStyle");
     AUTO_STRING (InputStyle, "InputStyle");
@@ -30872,10 +30907,19 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
 #ifdef USE_GTK
        else if (!strcmp (SSDATA (value), "native"))
          dpyinfo->prefer_native_input = true;
-#endif
+#endif /* HAVE_GTK */
       }
   }
-#endif
+
+  /* Now that defaults have been set up, initialize input method
+     support.  */
+
+  /* Avoid initializing input methods if the X library does not
+     support Emacs's locale.  When the current locale is not
+     supported, decoding input method strings becomes undefined.  */
+  if (XSupportsLocale ())
+    xim_initialize (dpyinfo, resource_name);
+#endif /* HAVE_X_I18N */
 
 #ifdef HAVE_X_SM
   /* Only do this for the very first display in the Emacs session.
@@ -31268,14 +31312,22 @@ x_delete_terminal (struct terminal *terminal)
 #ifdef HAVE_X_I18N
   /* We must close our connection to the XIM server before closing the
      X display.  */
-  if (dpyinfo->xim)
-    xim_close_dpy (dpyinfo);
+  xim_close_dpy (dpyinfo);
 #endif
 
+  /* Destroy all bitmap images created on the display.  */
+  image_destroy_all_bitmaps (dpyinfo);
+
+  /* Free the storage allocated to hold bitmap records.  */
+  xfree (dpyinfo->bitmaps);
+
+  /* In case someone decides to use `bitmaps' again... */
+  dpyinfo->bitmaps = NULL;
+  dpyinfo->bitmaps_last = 0;
+
   /* Normally, the display is available...  */
   if (dpyinfo->display)
     {
-      image_destroy_all_bitmaps (dpyinfo);
       XSetCloseDownMode (dpyinfo->display, DestroyAll);
 
       /* Delete the scratch cursor GC, should it exist.  */
diff --git a/src/xterm.h b/src/xterm.h
index 28ae00ca190..34a713ea2ca 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -649,7 +649,11 @@ struct x_display_info
 
   /* The named coding system to use for this input method.  */
   Lisp_Object xim_coding;
-#endif
+
+  /* Whether or not X input methods should be used on this
+     display.  */
+  bool use_xim;
+#endif /* HAVE_X_I18N */
 
   /* A cache mapping color names to RGB values.  */
   struct color_name_cache_entry **color_names;
@@ -922,11 +926,6 @@ struct x_display_info
 #endif
 };
 
-#ifdef HAVE_X_I18N
-/* Whether or not to use XIM if we have it.  */
-extern bool use_xim;
-#endif
-
 #ifdef HAVE_XINPUT2
 /* Defined in xmenu.c. */
 extern int popup_activated_flag;



reply via email to

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