# HG changeset patch # User Karoly Lorentey # Date 1148145163 0 # Node ID b2e7507b55c69a3a8153801a843b5fa337d8c64f # Parent 673d62ad74b51d5ad2abdf3b0b9b15962cfcf28b 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) : Doc update. * src/termhooks.h (terminal) : 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) : Move member earlier in the struct. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-565 diff -r 673d62ad74b5 -r b2e7507b55c6 src/frame.c --- a/src/frame.c Sat May 20 17:02:47 2006 +0000 +++ b/src/frame.c Sat May 20 17:12:43 2006 +0000 @@ -561,7 +561,10 @@ 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); diff -r 673d62ad74b5 -r b2e7507b55c6 src/keyboard.c --- a/src/keyboard.c Sat May 20 17:02:47 2006 +0000 +++ b/src/keyboard.c Sat May 20 17:12:43 2006 +0000 @@ -6899,6 +6899,9 @@ 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 (); diff -r 673d62ad74b5 -r b2e7507b55c6 src/term.c --- a/src/term.c Sat May 20 17:02:47 2006 +0000 +++ b/src/term.c Sat May 20 17:12:43 2006 +0000 @@ -2029,9 +2029,8 @@ 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 @@ { 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 @@ 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 @@ 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 @@ /* 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 @@ "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 @@ 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 @@ { 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 @@ 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 @@ bzero (tty, sizeof (struct tty_display_info)); xfree (tty); - deleting_tty = 0; } @@ -3096,14 +3086,14 @@ 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; diff -r 673d62ad74b5 -r b2e7507b55c6 src/termhooks.h --- a/src/termhooks.h Sat May 20 17:02:47 2006 +0000 +++ b/src/termhooks.h Sat May 20 17:12:43 2006 +0000 @@ -307,7 +307,9 @@ /* 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 diff -r 673d62ad74b5 -r b2e7507b55c6 src/terminal.c --- a/src/terminal.c Sat May 20 17:02:47 2006 +0000 +++ b/src/terminal.c Sat May 20 17:12:43 2006 +0000 @@ -270,7 +270,8 @@ } -/* 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 @@ 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); diff -r 673d62ad74b5 -r b2e7507b55c6 src/xfns.c --- a/src/xfns.c Sat May 20 17:02:47 2006 +0000 +++ b/src/xfns.c Sat May 20 17:12:43 2006 +0000 @@ -3039,6 +3039,9 @@ 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 @@ 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. */ diff -r 673d62ad74b5 -r b2e7507b55c6 src/xterm.c --- a/src/xterm.c Sat May 20 17:02:47 2006 +0000 +++ b/src/xterm.c Sat May 20 17:12:43 2006 +0000 @@ -6981,6 +6981,31 @@ ++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 @@ #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; - - XNextEvent (dpyinfo->display, &event); + while (XPending (terminal->display_info.x->display)) + { + int finish; + + 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; -#endif - event_found = 1; - - count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit); - - if (finish == X_EVENT_GOTO_OUT) - goto out; - } -#endif /* not USE_GTK */ - } - -#ifdef USE_GTK + /* Filter events for the current X input method. */ + if (x_filter_event (terminal->display_info.x, &event)) + break; +#endif + event_found = 1; + + count += handle_one_xevent (terminal->display_info.x, + &event, &finish, hold_quit); + + if (finish == X_EVENT_GOTO_OUT) + goto out; + } + +#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 @@ return dpyinfo; } -/* 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 @@ 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 @@ { 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. */ diff -r 673d62ad74b5 -r b2e7507b55c6 src/xterm.h --- a/src/xterm.h Sat May 20 17:02:47 2006 +0000 +++ b/src/xterm.h Sat May 20 17:12:43 2006 +0000 @@ -149,6 +149,9 @@ /* 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 @@ X_WMTYPE_A, X_WMTYPE_B } wm_type; - - /* The generic display parameters corresponding to this X display. */ - struct terminal *terminal; }; #ifdef HAVE_X_I18N