aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKaroly Lorentey2006-05-20 17:12:43 +0000
committerKaroly Lorentey2006-05-20 17:12:43 +0000
commitab797f65de1b82ff9e96aab6989976a152385048 (patch)
tree2622d33ce1a69cac40e5b31fa0f7f9e1faa8998b /src
parent8cbd7bed2db718a63ed37182c566f9e059925c71 (diff)
downloademacs-ab797f65de1b82ff9e96aab6989976a152385048.tar.gz
emacs-ab797f65de1b82ff9e96aab6989976a152385048.zip
Fix C-x 5 2 on the controlling tty; fix some possible crash conditions and a memory leak.
* 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
Diffstat (limited to 'src')
-rw-r--r--src/frame.c5
-rw-r--r--src/keyboard.c3
-rw-r--r--src/term.c66
-rw-r--r--src/termhooks.h4
-rw-r--r--src/terminal.c10
-rw-r--r--src/xfns.c6
-rw-r--r--src/xterm.c100
-rw-r--r--src/xterm.h6
8 files changed, 97 insertions, 103 deletions
diff --git a/src/frame.c b/src/frame.c
index f29bca1796f..3fad2187ba4 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -561,7 +561,10 @@ make_terminal_frame (struct terminal *terminal)
561 register struct frame *f; 561 register struct frame *f;
562 Lisp_Object frame; 562 Lisp_Object frame;
563 char name[20]; 563 char name[20];
564 564
565 if (terminal->deleted)
566 error ("Terminal is being deleted, can't create new frames on it");
567
565 f = make_frame (1); 568 f = make_frame (1);
566 569
567 XSETFRAME (frame, f); 570 XSETFRAME (frame, f);
diff --git a/src/keyboard.c b/src/keyboard.c
index 5dcd2f8f5ae..6e046aea7d6 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -6899,6 +6899,9 @@ tty_read_avail_input (struct terminal *terminal,
6899 struct tty_display_info *tty = terminal->display_info.tty; 6899 struct tty_display_info *tty = terminal->display_info.tty;
6900 int nread = 0; 6900 int nread = 0;
6901 6901
6902 if (terminal->deleted) /* Don't read from a deleted terminal. */
6903 return;
6904
6902 if (terminal->type != output_termcap) 6905 if (terminal->type != output_termcap)
6903 abort (); 6906 abort ();
6904 6907
diff --git a/src/term.c b/src/term.c
index 3076e8939f1..924bebf5f7e 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2029,9 +2029,8 @@ get_tty_terminal (Lisp_Object terminal, int throw)
2029 return t; 2029 return t;
2030} 2030}
2031 2031
2032/* Return the active termcap device that uses the tty device with the 2032/* Return an active termcap device that uses the tty device with the
2033 given name. If NAME is NULL, return the device corresponding to 2033 given name.
2034 our controlling terminal.
2035 2034
2036 This function ignores suspended devices. 2035 This function ignores suspended devices.
2037 2036
@@ -2043,14 +2042,16 @@ get_named_tty (name)
2043{ 2042{
2044 struct terminal *t; 2043 struct terminal *t;
2045 2044
2046 for (t = terminal_list; t; t = t->next_terminal) { 2045 if (!name)
2047 if (t->type == output_termcap 2046 abort ();
2048 && ((t->display_info.tty->name == 0 && name == 0) 2047
2049 || (name && t->display_info.tty->name 2048 for (t = terminal_list; t; t = t->next_terminal)
2050 && !strcmp (t->display_info.tty->name, name))) 2049 {
2051 && TERMINAL_ACTIVE_P (t)) 2050 if (t->type == output_termcap
2052 return t; 2051 && !strcmp (t->display_info.tty->name, name)
2053 }; 2052 && TERMINAL_ACTIVE_P (t))
2053 return t;
2054 }
2054 2055
2055 return 0; 2056 return 0;
2056} 2057}
@@ -2058,6 +2059,7 @@ get_named_tty (name)
2058 2059
2059DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0, 2060DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2060 doc: /* Return the type of the tty device that TERMINAL uses. 2061 doc: /* Return the type of the tty device that TERMINAL uses.
2062Returns nil if TERMINAL is not on a tty device.
2061 2063
2062TERMINAL can be a terminal id, a frame or nil (meaning the selected 2064TERMINAL can be a terminal id, a frame or nil (meaning the selected
2063frame's terminal). */) 2065frame's terminal). */)
@@ -2067,8 +2069,8 @@ frame's terminal). */)
2067 struct terminal *t = get_terminal (terminal, 1); 2069 struct terminal *t = get_terminal (terminal, 1);
2068 2070
2069 if (t->type != output_termcap) 2071 if (t->type != output_termcap)
2070 error ("Terminal %d is not a termcap terminal", t->id); 2072 return Qnil;
2071 2073
2072 if (t->display_info.tty->type) 2074 if (t->display_info.tty->type)
2073 return build_string (t->display_info.tty->type); 2075 return build_string (t->display_info.tty->type);
2074 else 2076 else
@@ -2388,7 +2390,7 @@ static void maybe_fatal();
2388/* Create a termcap display on the tty device with the given name and 2390/* Create a termcap display on the tty device with the given name and
2389 type. 2391 type.
2390 2392
2391 If NAME is NULL, then use the controlling tty, i.e., stdin/stdout. 2393 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
2392 Otherwise NAME should be a path to the tty device file, 2394 Otherwise NAME should be a path to the tty device file,
2393 e.g. "/dev/pts/7". 2395 e.g. "/dev/pts/7".
2394 2396
@@ -2414,6 +2416,11 @@ init_tty (char *name, char *terminal_type, int must_succeed)
2414 "Unknown terminal type", 2416 "Unknown terminal type",
2415 "Unknown terminal type"); 2417 "Unknown terminal type");
2416 2418
2419 if (name == NULL)
2420 name = "/dev/tty";
2421 if (!strcmp (name, "/dev/tty"))
2422 ctty = 1;
2423
2417 /* If we already have a terminal on the given device, use that. If 2424 /* If we already have a terminal on the given device, use that. If
2418 all such terminals are suspended, create a new one instead. */ 2425 all such terminals are suspended, create a new one instead. */
2419 /* XXX Perhaps this should be made explicit by having init_tty 2426 /* 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)
2438 2445
2439 set_tty_hooks (terminal); 2446 set_tty_hooks (terminal);
2440 2447
2441 if (name == NULL)
2442 name = "/dev/tty";
2443 if (!strcmp (name, "/dev/tty"))
2444 ctty = 1;
2445
2446 { 2448 {
2447 int fd; 2449 int fd;
2448 FILE *file; 2450 FILE *file;
@@ -2977,11 +2979,10 @@ delete_tty (struct terminal *terminal)
2977{ 2979{
2978 struct tty_display_info *tty; 2980 struct tty_display_info *tty;
2979 Lisp_Object tail, frame; 2981 Lisp_Object tail, frame;
2980 char *tty_name;
2981 int last_terminal; 2982 int last_terminal;
2982 2983
2983 /* Protect against recursive calls. Fdelete_frame calls us back 2984 /* Protect against recursive calls. Fdelete_frame in
2984 when we delete our last frame. */ 2985 delete_terminal calls us back when it deletes our last frame. */
2985 if (terminal->deleted) 2986 if (terminal->deleted)
2986 return; 2987 return;
2987 2988
@@ -3019,25 +3020,15 @@ delete_tty (struct terminal *terminal)
3019 tty->next = 0; 3020 tty->next = 0;
3020 } 3021 }
3021 3022
3022 /* We must not throw any errors below this line. */
3023 terminal->deleted = 1;
3024
3025 FOR_EACH_FRAME (tail, frame)
3026 {
3027 struct frame *f = XFRAME (frame);
3028 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
3029 {
3030 Fdelete_frame (frame, Qt);
3031 }
3032 }
3033
3034 /* reset_sys_modes needs a valid device, so this call needs to be 3023 /* reset_sys_modes needs a valid device, so this call needs to be
3035 before delete_terminal. */ 3024 before delete_terminal. */
3036 reset_sys_modes (tty); 3025 reset_sys_modes (tty);
3037 3026
3038 delete_terminal (terminal); 3027 delete_terminal (terminal);
3039 3028
3040 tty_name = tty->name; 3029 if (tty->name)
3030 xfree (tty->name);
3031
3041 if (tty->type) 3032 if (tty->type)
3042 xfree (tty->type); 3033 xfree (tty->type);
3043 3034
@@ -3060,7 +3051,6 @@ delete_tty (struct terminal *terminal)
3060 3051
3061 bzero (tty, sizeof (struct tty_display_info)); 3052 bzero (tty, sizeof (struct tty_display_info));
3062 xfree (tty); 3053 xfree (tty);
3063 deleting_tty = 0;
3064} 3054}
3065 3055
3066 3056
@@ -3096,14 +3086,14 @@ This variable can be used by terminal emulator packages. */);
3096 3086
3097 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions, 3087 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3098 doc: /* Functions to be run after suspending a tty. 3088 doc: /* Functions to be run after suspending a tty.
3099The functions are run with one argument, the name of the tty to be suspended. 3089The functions are run with one argument, the terminal id to be suspended.
3100See `suspend-tty'. */); 3090See `suspend-tty'. */);
3101 Vsuspend_tty_functions = Qnil; 3091 Vsuspend_tty_functions = Qnil;
3102 3092
3103 3093
3104 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions, 3094 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3105 doc: /* Functions to be run after resuming a tty. 3095 doc: /* Functions to be run after resuming a tty.
3106The functions are run with one argument, the name of the tty that was revived. 3096The functions are run with one argument, the terminal id that was revived.
3107See `resume-tty'. */); 3097See `resume-tty'. */);
3108 Vresume_tty_functions = Qnil; 3098 Vresume_tty_functions = Qnil;
3109 3099
diff --git a/src/termhooks.h b/src/termhooks.h
index 46fb0c453f5..64a72acc360 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -307,7 +307,9 @@ struct terminal
307 /* The type of the terminal device. */ 307 /* The type of the terminal device. */
308 enum output_method type; 308 enum output_method type;
309 309
310 /* The name of the terminal device. Do not use this to identify the device. */ 310 /* The name of the terminal device. Do not use this to uniquely
311 identify a terminal; the same device may be opened multiple
312 times. */
311 char *name; 313 char *name;
312 314
313#ifdef MULTI_KBOARD 315#ifdef MULTI_KBOARD
diff --git a/src/terminal.c b/src/terminal.c
index db75e16b6cf..f3f0a178c8d 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -270,7 +270,8 @@ mark_terminals (void)
270} 270}
271 271
272 272
273/* Remove a terminal from the terminal list and free its memory. */ 273/* Low-level function to close all frames on a terminal, remove it
274 from the terminal list and free its memory. */
274 275
275void 276void
276delete_terminal (struct terminal *terminal) 277delete_terminal (struct terminal *terminal)
@@ -278,14 +279,13 @@ delete_terminal (struct terminal *terminal)
278 struct terminal **tp; 279 struct terminal **tp;
279 Lisp_Object tail, frame; 280 Lisp_Object tail, frame;
280 281
281 /* Protect against recursive calls. Fdelete_frame calls us back 282 /* Protect against recursive calls. Fdelete_frame calls the
282 when we delete our last frame. */ 283 delete_terminal_hook when we delete our last frame. */
283 if (terminal->deleted) 284 if (terminal->deleted)
284 return; 285 return;
285 terminal->deleted = 1; 286 terminal->deleted = 1;
286 287
287 /* Check for and close live frames that are still on this 288 /* Check for live frames that are still on this terminal. */
288 terminal. */
289 FOR_EACH_FRAME (tail, frame) 289 FOR_EACH_FRAME (tail, frame)
290 { 290 {
291 struct frame *f = XFRAME (frame); 291 struct frame *f = XFRAME (frame);
diff --git a/src/xfns.c b/src/xfns.c
index 43970439a1a..acbf22b600c 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3039,6 +3039,9 @@ This function is an internal primitive--use `make-frame' instead. */)
3039 kb = &the_only_kboard; 3039 kb = &the_only_kboard;
3040#endif 3040#endif
3041 3041
3042 if (dpyinfo->terminal->deleted)
3043 error ("Terminal is being deleted, can't create new frames on it");
3044
3042 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); 3045 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3043 if (!STRINGP (name) 3046 if (!STRINGP (name)
3044 && ! EQ (name, Qunbound) 3047 && ! EQ (name, Qunbound)
@@ -4634,6 +4637,9 @@ x_create_tip_frame (dpyinfo, parms, text)
4634 4637
4635 check_x (); 4638 check_x ();
4636 4639
4640 if (dpyinfo->terminal->deleted)
4641 error ("Terminal is being deleted, can't create new frames on it");
4642
4637 parms = Fcopy_alist (parms); 4643 parms = Fcopy_alist (parms);
4638 4644
4639 /* Get the name of the frame to use for resource lookup. */ 4645 /* Get the name of the frame to use for resource lookup. */
diff --git a/src/xterm.c b/src/xterm.c
index 04242f2af3b..356ee3b963b 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -6981,6 +6981,31 @@ XTread_socket (terminal, expected, hold_quit)
6981 6981
6982 ++handling_signal; 6982 ++handling_signal;
6983 6983
6984#ifdef HAVE_X_SM
6985 /* Only check session manager input for the primary display. */
6986 if (terminal->id == 1 && x_session_have_connection ())
6987 {
6988 struct input_event inev;
6989 BLOCK_INPUT;
6990 /* We don't need to EVENT_INIT (inev) here, as
6991 x_session_check_input copies an entire input_event. */
6992 if (x_session_check_input (&inev))
6993 {
6994 kbd_buffer_store_event_hold (&inev, hold_quit);
6995 count++;
6996 }
6997 UNBLOCK_INPUT;
6998 }
6999#endif
7000
7001 /* For debugging, this gives a way to fake an I/O error. */
7002 if (terminal->display_info.x == XTread_socket_fake_io_error)
7003 {
7004 XTread_socket_fake_io_error = 0;
7005 x_io_error_quitter (dpyinfo->display);
7006 }
7007
7008#if 0 /* This loop is a noop now. */
6984 /* Find the display we are supposed to read input for. 7009 /* Find the display we are supposed to read input for.
6985 It's the one communicating on descriptor SD. */ 7010 It's the one communicating on descriptor SD. */
6986 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) 7011 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -7011,54 +7036,31 @@ XTread_socket (terminal, expected, hold_quit)
7011#endif /* HAVE_SELECT */ 7036#endif /* HAVE_SELECT */
7012#endif /* SIGIO */ 7037#endif /* SIGIO */
7013#endif 7038#endif
7014 7039 }
7015 /* For debugging, this gives a way to fake an I/O error. */
7016 if (dpyinfo == XTread_socket_fake_io_error)
7017 {
7018 XTread_socket_fake_io_error = 0;
7019 x_io_error_quitter (dpyinfo->display);
7020 }
7021
7022#ifdef HAVE_X_SM
7023 /* Only check session manager input for the primary display. */
7024 if (terminal->id == 1 && x_session_have_connection ())
7025 {
7026 struct input_event inev;
7027 BLOCK_INPUT;
7028 /* We don't need to EVENT_INIT (inev) here, as
7029 x_session_check_input copies an entire input_event. */
7030 if (x_session_check_input (&inev))
7031 {
7032 kbd_buffer_store_event_hold (&inev, hold_quit);
7033 count++;
7034 }
7035 UNBLOCK_INPUT;
7036 }
7037#endif 7040#endif
7038 7041
7039#ifndef USE_GTK 7042#ifndef USE_GTK
7040 while (XPending (dpyinfo->display)) 7043 while (XPending (terminal->display_info.x->display))
7041 { 7044 {
7042 int finish; 7045 int finish;
7043 7046
7044 XNextEvent (dpyinfo->display, &event); 7047 XNextEvent (terminal->display_info.x->display, &event);
7045 7048
7046#ifdef HAVE_X_I18N 7049#ifdef HAVE_X_I18N
7047 /* Filter events for the current X input method. */ 7050 /* Filter events for the current X input method. */
7048 if (x_filter_event (dpyinfo, &event)) 7051 if (x_filter_event (terminal->display_info.x, &event))
7049 break; 7052 break;
7050#endif 7053#endif
7051 event_found = 1; 7054 event_found = 1;
7052 7055
7053 count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit); 7056 count += handle_one_xevent (terminal->display_info.x,
7057 &event, &finish, hold_quit);
7054 7058
7055 if (finish == X_EVENT_GOTO_OUT) 7059 if (finish == X_EVENT_GOTO_OUT)
7056 goto out; 7060 goto out;
7057 }
7058#endif /* not USE_GTK */
7059 } 7061 }
7060 7062
7061#ifdef USE_GTK 7063#else /* USE_GTK */
7062 7064
7063 /* For GTK we must use the GTK event loop. But XEvents gets passed 7065 /* For GTK we must use the GTK event loop. But XEvents gets passed
7064 to our filter function above, and then to the big event switch. 7066 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)
10680 return dpyinfo; 10682 return dpyinfo;
10681} 10683}
10682 10684
10683/* Get rid of display DPYINFO, assuming all frames are already gone, 10685/* Get rid of display DPYINFO, deleting all frames on it,
10684 and without sending any more commands to the X server. */ 10686 and without sending any more commands to the X server. */
10685 10687
10686void 10688void
@@ -10690,11 +10692,12 @@ x_delete_display (dpyinfo)
10690 int i; 10692 int i;
10691 struct terminal *t; 10693 struct terminal *t;
10692 10694
10693 /* Delete the generic struct terminal for this X display. */ 10695 /* Close all frames and delete the generic struct terminal for this
10696 X display. */
10694 for (t = terminal_list; t; t = t->next_terminal) 10697 for (t = terminal_list; t; t = t->next_terminal)
10695 if (t->type == output_x_window && t->display_info.x == dpyinfo) 10698 if (t->type == output_x_window && t->display_info.x == dpyinfo)
10696 { 10699 {
10697 /* Close X session management when we close its display. */ 10700 /* Close X session management when we close its display. */
10698 if (t->id == 1 && x_session_have_connection ()) 10701 if (t->id == 1 && x_session_have_connection ())
10699 x_session_close(); 10702 x_session_close();
10700 10703
@@ -10837,24 +10840,11 @@ x_delete_terminal (struct terminal *terminal)
10837{ 10840{
10838 struct x_display_info *dpyinfo = terminal->display_info.x; 10841 struct x_display_info *dpyinfo = terminal->display_info.x;
10839 int i; 10842 int i;
10840 Lisp_Object tail, frame;
10841 10843
10842 /* Protect against recursive calls. Fdelete_frame calls us back 10844 /* Protect against recursive calls. Fdelete_frame in
10843 when we delete our last frame. */ 10845 delete_terminal calls us back when it deletes our last frame. */
10844 if (terminal->deleted) 10846 if (terminal->deleted)
10845 return; 10847 return;
10846 terminal->deleted = 1;
10847
10848 /* Check for and close live frames that are still on this
10849 terminal. */
10850 FOR_EACH_FRAME (tail, frame)
10851 {
10852 struct frame *f = XFRAME (frame);
10853 if (FRAME_LIVE_P (f) && f->terminal == terminal)
10854 {
10855 Fdelete_frame (frame, Qt);
10856 }
10857 }
10858 10848
10859 BLOCK_INPUT; 10849 BLOCK_INPUT;
10860 /* Free the fonts in the font table. */ 10850 /* Free the fonts in the font table. */
diff --git a/src/xterm.h b/src/xterm.h
index 5f37a23448c..b54c39f2fd0 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -149,6 +149,9 @@ struct x_display_info
149 /* Chain of all x_display_info structures. */ 149 /* Chain of all x_display_info structures. */
150 struct x_display_info *next; 150 struct x_display_info *next;
151 151
152 /* The generic display parameters corresponding to this X display. */
153 struct terminal *terminal;
154
152 /* Connection number (normally a file descriptor number). */ 155 /* Connection number (normally a file descriptor number). */
153 int connection; 156 int connection;
154 157
@@ -386,9 +389,6 @@ struct x_display_info
386 X_WMTYPE_A, 389 X_WMTYPE_A,
387 X_WMTYPE_B 390 X_WMTYPE_B
388 } wm_type; 391 } wm_type;
389
390 /* The generic display parameters corresponding to this X display. */
391 struct terminal *terminal;
392}; 392};
393 393
394#ifdef HAVE_X_I18N 394#ifdef HAVE_X_I18N