=== modified file 'src/frame.c' --- src/frame.c 2013-08-14 16:36:16 +0000 +++ src/frame.c 2013-08-14 17:28:21 +0000 @@ -1199,8 +1199,14 @@ { Lisp_Object tail, frame1; - /* Look for another visible frame on the same terminal. */ - frame1 = next_frame (frame, Qvisible); + /* Look for another visible frame on the same terminal. + Do not call next_frame here. FIXME this. */ + FOR_EACH_FRAME (tail, frame1) + if (!EQ (frame, frame1) + && (FRAME_TERMINAL (XFRAME (frame)) + == FRAME_TERMINAL (XFRAME (frame1))) + && FRAME_VISIBLE_P (XFRAME (frame1))) + break; /* If there is none, find *some* other frame. */ if (NILP (frame1) || EQ (frame1, frame)) === modified file 'src/keyboard.c' --- src/keyboard.c 2013-08-13 08:39:14 +0000 +++ src/keyboard.c 2013-08-14 17:12:39 +0000 @@ -6847,17 +6847,21 @@ alone in its group. */ terminate_due_to_signal (SIGHUP, 10); - /* XXX Is calling delete_terminal safe here? It calls delete_frame. */ - { - Lisp_Object tmp; - XSETTERMINAL (tmp, t); - Fdelete_terminal (tmp, Qnoelisp); - } + /* This terminal is now dead. */ + t->dead = 1; } if (hold_quit.kind != NO_EVENT) kbd_buffer_store_event (&hold_quit); } + else + { + /* If read_socket_hook is NULL, T is suspended. But T may be + dead, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */ + if (t->type == output_termcap + && !check_tty_alive (t->display_info.tty->name)) + t->dead = 1; + } t = next; } @@ -7079,6 +7083,7 @@ { pending_signals = 0; handle_async_input (); + drop_dead_terminals (); do_pending_atimers (); } === modified file 'src/lisp.h' --- src/lisp.h 2013-08-14 16:36:16 +0000 +++ src/lisp.h 2013-08-14 17:14:11 +0000 @@ -4094,6 +4094,7 @@ extern void sys_subshell (void); extern void sys_suspend (void); extern void discard_tty_input (void); +extern bool check_tty_alive (char *); extern void block_tty_out_signal (void); extern void unblock_tty_out_signal (void); extern void init_sys_modes (struct tty_display_info *); === modified file 'src/sysdep.c' --- src/sysdep.c 2013-08-09 12:25:34 +0000 +++ src/sysdep.c 2013-08-14 17:13:48 +0000 @@ -734,6 +734,15 @@ #endif } +/* This works on Linux, but no ideas for others. */ + +bool +check_tty_alive (char *tty) +{ + int fd = emacs_open (tty, O_RDWR | O_NONBLOCK, 0); + return fd > 0 ? (emacs_close (fd), 1) : 0; +} + /* Safely set a controlling terminal FD's process group to PGID. If we are not in the foreground already, POSIX requires tcsetpgrp to deliver a SIGTTOU signal, which would stop us. This is an === modified file 'src/termhooks.h' --- src/termhooks.h 2013-07-16 11:41:06 +0000 +++ src/termhooks.h 2013-08-14 17:04:49 +0000 @@ -362,6 +362,9 @@ /* Chain of all terminal devices. */ struct terminal *next_terminal; + /* Nonzero if this terminal is really dead. */ + unsigned dead : 1; + /* Unique id for this terminal device. */ int id; @@ -648,6 +651,7 @@ extern struct terminal *get_terminal (Lisp_Object terminal, bool); extern struct terminal *create_terminal (void); extern void delete_terminal (struct terminal *); +extern void drop_dead_terminals (void); /* The initial terminal device, created by initial_term_init. */ extern struct terminal *initial_terminal; === modified file 'src/terminal.c' --- src/terminal.c 2013-07-31 06:05:05 +0000 +++ src/terminal.c 2013-08-14 17:36:30 +0000 @@ -537,6 +537,24 @@ } void +drop_dead_terminals (void) +{ + struct terminal *t, *next; + + for (t = terminal_list; t; t = next) + { + next = t->next_terminal; + if (t->dead) + { + if (t->delete_terminal_hook) + (*t->delete_terminal_hook) (t); + else + delete_terminal (t); + } + } +} + +void syms_of_terminal (void) {