Commit ab797f65 authored by Karoly Lorentey's avatar Karoly Lorentey

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
parent 8cbd7bed
......@@ -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);
......
......@@ -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 ();
......
......@@ -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)
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;
}
......@@ -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;
......
......@@ -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
......
......@@ -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);
......
......@@ -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. */
......
......@@ -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;
}
/* 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. */
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment