]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix C-x 5 2 on the controlling tty; fix some possible crash conditions and a memory...
authorKaroly Lorentey <lorentey@elte.hu>
Sat, 20 May 2006 17:12:43 +0000 (17:12 +0000)
committerKaroly Lorentey <lorentey@elte.hu>
Sat, 20 May 2006 17:12:43 +0000 (17:12 +0000)
* src/frame.c (make_terminal_frame): Don't create frames on a terminal
  that is being deleted.
* src/xfns.c (Fx_create_frame, x_create_tip_frame): Ditto.

* src/keyboard.c (tty_read_avail_input): Don't read from a terminal that
  is being deleted.

* src/term.c (get_named_tty): Abort if tty name is NULL.  Simplify accordingly.

* src/term.c (Ftty_type): Return nil if terminal is not on a tty instead
  of throwing an error.  Doc update.

* src/term.c (init_tty): Set name before calling `get_named_tty'.

* src/term.c (delete_tty): Let delete_terminal delete the frames.  Plug
  memory leak caused by tty->name.  Remove reference to `deleting_tty'.

* src/term.c (syms_of_term) <Vsuspend_tty_functions, Vresume_tty_functions>: Doc update.

* src/termhooks.h (terminal) <name>: Explain why identifying terminals by
  name is a bad idea.

* src/terminal.c (delete_terminal): Doc update.

* src/xterm.c (XTread_socket): Disable loop on all X displays.

* src/xterm.c (x_delete_display): Doc update to reflect changes in
  delete_terminal.

* src/xterm.c (x_delete_terminal): Don't set terminal->deleted and let
  delete_terminal delete the frames on the terminal.

* src/xterm.h (x_display_info) <terminal>: Move member earlier in the struct.

git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-565

src/frame.c
src/keyboard.c
src/term.c
src/termhooks.h
src/terminal.c
src/xfns.c
src/xterm.c
src/xterm.h

index f29bca1796f7a3011bb50b946cc378f3f61582a3..3fad2187ba4ca9fa038c347ba47d4627472cba4b 100644 (file)
@@ -561,7 +561,10 @@ make_terminal_frame (struct terminal *terminal)
   register struct frame *f;
   Lisp_Object frame;
   char name[20];
-  
+
+  if (terminal->deleted)
+    error ("Terminal is being deleted, can't create new frames on it");
+
   f = make_frame (1);
 
   XSETFRAME (frame, f);
index 5dcd2f8f5ae97fba2b36434a2a165a656843746f..6e046aea7d60bfff22fba3e801ffe3d5f30ade04 100644 (file)
@@ -6899,6 +6899,9 @@ tty_read_avail_input (struct terminal *terminal,
   struct tty_display_info *tty = terminal->display_info.tty;
   int nread = 0;
 
+  if (terminal->deleted)        /* Don't read from a deleted terminal. */
+    return;
+
   if (terminal->type != output_termcap)
     abort ();
 
index 3076e8939f19ba6cc15a9c8878e192bcb1826248..924bebf5f7eea4e75c8737093873a567dbeecb17 100644 (file)
@@ -2029,9 +2029,8 @@ get_tty_terminal (Lisp_Object terminal, int throw)
   return t;
 }
 
-/* Return the active termcap device that uses the tty device with the
-   given name.  If NAME is NULL, return the device corresponding to
-   our controlling terminal.
+/* Return an active termcap device that uses the tty device with the
+   given name.
 
    This function ignores suspended devices.
 
@@ -2043,14 +2042,16 @@ get_named_tty (name)
 {
   struct terminal *t;
 
-  for (t = terminal_list; t; t = t->next_terminal) {
-    if (t->type == output_termcap
-        && ((t->display_info.tty->name == 0 && name == 0)
-            || (name && t->display_info.tty->name
-                && !strcmp (t->display_info.tty->name, name)))
-        && TERMINAL_ACTIVE_P (t))
-      return t;
-  };
+  if (!name)
+    abort ();
+
+  for (t = terminal_list; t; t = t->next_terminal)
+    {
+      if (t->type == output_termcap
+          && !strcmp (t->display_info.tty->name, name)
+          && TERMINAL_ACTIVE_P (t))
+        return t;
+    }
 
   return 0;
 }
@@ -2058,6 +2059,7 @@ get_named_tty (name)
 \f
 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
        doc: /* Return the type of the tty device that TERMINAL uses.
+Returns nil if TERMINAL is not on a tty device.
 
 TERMINAL can be a terminal id, a frame or nil (meaning the selected
 frame's terminal).  */)
@@ -2067,8 +2069,8 @@ frame's terminal).  */)
   struct terminal *t = get_terminal (terminal, 1);
 
   if (t->type != output_termcap)
-    error ("Terminal %d is not a termcap terminal", t->id);
-           
+    return Qnil;
+
   if (t->display_info.tty->type)
     return build_string (t->display_info.tty->type);
   else
@@ -2388,7 +2390,7 @@ static void maybe_fatal();
 /* Create a termcap display on the tty device with the given name and
    type.
 
-   If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
+   If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
    Otherwise NAME should be a path to the tty device file,
    e.g. "/dev/pts/7".
 
@@ -2414,6 +2416,11 @@ init_tty (char *name, char *terminal_type, int must_succeed)
                  "Unknown terminal type",
                  "Unknown terminal type");
 
+  if (name == NULL)
+    name = "/dev/tty";
+  if (!strcmp (name, "/dev/tty"))
+    ctty = 1;
+
   /* If we already have a terminal on the given device, use that.  If
      all such terminals are suspended, create a new one instead.  */
   /* XXX Perhaps this should be made explicit by having init_tty
@@ -2438,11 +2445,6 @@ init_tty (char *name, char *terminal_type, int must_succeed)
 
   set_tty_hooks (terminal);
   
-  if (name == NULL)
-    name = "/dev/tty";
-  if (!strcmp (name, "/dev/tty"))
-    ctty = 1;
-
   {
     int fd;
     FILE *file;
@@ -2977,11 +2979,10 @@ delete_tty (struct terminal *terminal)
 {
   struct tty_display_info *tty;
   Lisp_Object tail, frame;
-  char *tty_name;
   int last_terminal;
   
-  /* Protect against recursive calls.  Fdelete_frame calls us back
-     when we delete our last frame.  */
+  /* Protect against recursive calls.  Fdelete_frame in
+     delete_terminal calls us back when it deletes our last frame.  */
   if (terminal->deleted)
     return;
 
@@ -3019,25 +3020,15 @@ delete_tty (struct terminal *terminal)
       tty->next = 0;
     }
 
-  /* We must not throw any errors below this line.  */
-  terminal->deleted = 1;
-
-  FOR_EACH_FRAME (tail, frame)
-    {
-      struct frame *f = XFRAME (frame);
-      if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
-        {
-          Fdelete_frame (frame, Qt);
-        }
-    }
-
   /* reset_sys_modes needs a valid device, so this call needs to be
      before delete_terminal. */
   reset_sys_modes (tty);
 
   delete_terminal (terminal);
 
-  tty_name = tty->name;
+  if (tty->name)
+    xfree (tty->name);
+
   if (tty->type)
     xfree (tty->type);
 
@@ -3060,7 +3051,6 @@ delete_tty (struct terminal *terminal)
 
   bzero (tty, sizeof (struct tty_display_info));
   xfree (tty);
-  deleting_tty = 0;
 }
 
 \f
@@ -3096,14 +3086,14 @@ This variable can be used by terminal emulator packages.  */);
 
   DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
     doc: /* Functions to be run after suspending a tty.
-The functions are run with one argument, the name of the tty to be suspended.
+The functions are run with one argument, the terminal id to be suspended.
 See `suspend-tty'.  */);
   Vsuspend_tty_functions = Qnil;
 
 
   DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
     doc: /* Functions to be run after resuming a tty.
-The functions are run with one argument, the name of the tty that was revived.
+The functions are run with one argument, the terminal id that was revived.
 See `resume-tty'.  */);
   Vresume_tty_functions = Qnil;
 
index 46fb0c453f5ab027729c08cd8d173297ee31fdfe..64a72acc36054de668e10aee6f6d853017e73e7f 100644 (file)
@@ -307,7 +307,9 @@ struct terminal
   /* The type of the terminal device. */
   enum output_method type;
 
-  /* The name of the terminal device.  Do not use this to identify the device. */
+  /* The name of the terminal device.  Do not use this to uniquely
+     identify a terminal; the same device may be opened multiple
+     times. */
   char *name;
 
 #ifdef MULTI_KBOARD
index db75e16b6cfd187e8bbade486391a167e1ce88b1..f3f0a178c8d54ab05a7f450b0e4af5b225494c76 100644 (file)
@@ -270,7 +270,8 @@ mark_terminals (void)
 }
 
 
-/* Remove a terminal from the terminal list and free its memory. */
+/* Low-level function to close all frames on a terminal, remove it
+   from the terminal list and free its memory.  */
 
 void
 delete_terminal (struct terminal *terminal)
@@ -278,14 +279,13 @@ delete_terminal (struct terminal *terminal)
   struct terminal **tp;
   Lisp_Object tail, frame;
 
-  /* Protect against recursive calls.  Fdelete_frame calls us back
-     when we delete our last frame.  */
+  /* Protect against recursive calls.  Fdelete_frame calls the
+     delete_terminal_hook when we delete our last frame.  */
   if (terminal->deleted)
     return;
   terminal->deleted = 1;
 
-  /* Check for and close live frames that are still on this
-     terminal. */
+  /* Check for live frames that are still on this terminal. */
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
index 43970439a1ab2b618e45a392627fb4b1b0d28cc7..acbf22b600c7db2f92c827faae2b8d1aabe6b8b5 100644 (file)
@@ -3039,6 +3039,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   kb = &the_only_kboard;
 #endif
 
+  if (dpyinfo->terminal->deleted)
+    error ("Terminal is being deleted, can't create new frames on it");
+
   name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && ! EQ (name, Qunbound)
@@ -4634,6 +4637,9 @@ x_create_tip_frame (dpyinfo, parms, text)
 
   check_x ();
 
+  if (dpyinfo->terminal->deleted)
+    error ("Terminal is being deleted, can't create new frames on it");
+
   parms = Fcopy_alist (parms);
 
   /* Get the name of the frame to use for resource lookup.  */
index 04242f2af3b090c7efb66319ad4a61c7ef4233b8..356ee3b963b278bce9475e7b13d10d90c7b02de4 100644 (file)
@@ -6981,6 +6981,31 @@ XTread_socket (terminal, expected, hold_quit)
 
   ++handling_signal;
 
+#ifdef HAVE_X_SM
+  /* Only check session manager input for the primary display. */
+  if (terminal->id == 1 && x_session_have_connection ())
+    {
+      struct input_event inev;
+      BLOCK_INPUT;
+      /* We don't need to EVENT_INIT (inev) here, as
+         x_session_check_input copies an entire input_event.  */
+      if (x_session_check_input (&inev))
+        {
+          kbd_buffer_store_event_hold (&inev, hold_quit);
+          count++;
+        }
+      UNBLOCK_INPUT;
+    }
+#endif
+
+  /* For debugging, this gives a way to fake an I/O error.  */
+  if (terminal->display_info.x == XTread_socket_fake_io_error)
+    {
+      XTread_socket_fake_io_error = 0;
+      x_io_error_quitter (dpyinfo->display);
+    }
+  
+#if 0 /* This loop is a noop now.  */
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -7011,54 +7036,31 @@ XTread_socket (terminal, expected, hold_quit)
 #endif /* HAVE_SELECT */
 #endif /* SIGIO */
 #endif
-
-      /* For debugging, this gives a way to fake an I/O error.  */
-      if (dpyinfo == XTread_socket_fake_io_error)
-       {
-         XTread_socket_fake_io_error = 0;
-         x_io_error_quitter (dpyinfo->display);
-       }
-
-#ifdef HAVE_X_SM
-      /* Only check session manager input for the primary display. */
-      if (terminal->id == 1 && x_session_have_connection ())
-        {
-          struct input_event inev;
-          BLOCK_INPUT;
-          /* We don't need to EVENT_INIT (inev) here, as
-             x_session_check_input copies an entire input_event.  */
-          if (x_session_check_input (&inev))
-            {
-              kbd_buffer_store_event_hold (&inev, hold_quit);
-              count++;
-            }
-          UNBLOCK_INPUT;
-        }
+    }
 #endif
 
 #ifndef USE_GTK
-      while (XPending (dpyinfo->display))
-       {
-          int finish;
+  while (XPending (terminal->display_info.x->display))
+    {
+      int finish;
 
-         XNextEvent (dpyinfo->display, &event);
+      XNextEvent (terminal->display_info.x->display, &event);
 
 #ifdef HAVE_X_I18N
-          /* Filter events for the current X input method.  */
-          if (x_filter_event (dpyinfo, &event))
-            break;
+      /* Filter events for the current X input method.  */
+      if (x_filter_event (terminal->display_info.x, &event))
+        break;
 #endif
-         event_found = 1;
+      event_found = 1;
 
-          count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
+      count += handle_one_xevent (terminal->display_info.x,
+                                  &event, &finish, hold_quit);
 
-          if (finish == X_EVENT_GOTO_OUT)
-            goto out;
-        }
-#endif /* not USE_GTK */
+      if (finish == X_EVENT_GOTO_OUT)
+        goto out;
     }
 
-#ifdef USE_GTK
+#else /* USE_GTK */
 
   /* For GTK we must use the GTK event loop.  But XEvents gets passed
      to our filter function above, and then to the big event switch.
@@ -10680,7 +10682,7 @@ x_term_init (display_name, xrm_option, resource_name)
   return dpyinfo;
 }
 \f
-/* Get rid of display DPYINFO, assuming all frames are already gone,
+/* Get rid of display DPYINFO, deleting all frames on it,
    and without sending any more commands to the X server.  */
 
 void
@@ -10690,11 +10692,12 @@ x_delete_display (dpyinfo)
   int i;
   struct terminal *t;
 
-  /* Delete the generic struct terminal for this X display. */
+  /* Close all frames and delete the generic struct terminal for this
+     X display.  */
   for (t = terminal_list; t; t = t->next_terminal)
     if (t->type == output_x_window && t->display_info.x == dpyinfo)
       {
-        /* Close X session management when we close its display. */
+        /* Close X session management when we close its display.  */
         if (t->id == 1 && x_session_have_connection ())
           x_session_close();
 
@@ -10837,24 +10840,11 @@ x_delete_terminal (struct terminal *terminal)
 {
   struct x_display_info *dpyinfo = terminal->display_info.x;
   int i;
-  Lisp_Object tail, frame;
 
-  /* Protect against recursive calls.  Fdelete_frame calls us back
-     when we delete our last frame.  */
+  /* Protect against recursive calls.  Fdelete_frame in
+     delete_terminal calls us back when it deletes our last frame.  */
   if (terminal->deleted)
     return;
-  terminal->deleted = 1;
-
-  /* Check for and close live frames that are still on this
-     terminal. */
-  FOR_EACH_FRAME (tail, frame)
-    {
-      struct frame *f = XFRAME (frame);
-      if (FRAME_LIVE_P (f) && f->terminal == terminal)
-        {
-          Fdelete_frame (frame, Qt);
-        }
-    }
 
   BLOCK_INPUT;
   /* Free the fonts in the font table.  */
index 5f37a23448c26cada44fd1294272db987155bfae..b54c39f2fd0562645027c5f96f6b61f998e3d1ee 100644 (file)
@@ -149,6 +149,9 @@ struct x_display_info
   /* Chain of all x_display_info structures.  */
   struct x_display_info *next;
 
+  /* The generic display parameters corresponding to this X display. */
+  struct terminal *terminal;
+
   /* Connection number (normally a file descriptor number).  */
   int connection;
 
@@ -386,9 +389,6 @@ struct x_display_info
       X_WMTYPE_A,
       X_WMTYPE_B
     } wm_type;
-
-  /* The generic display parameters corresponding to this X display. */
-  struct terminal *terminal;
 };
 
 #ifdef HAVE_X_I18N