Mercurial > emacs
changeset 82991:2b26656ff804
MULTI_KBOARD support for ttys. Input-related bugfixes for X+tty sessions.
lib-src/emacsclient.c (pty_conversation): Fix errno check for read from fileno(in).
src/config.in: Unconditionally define MULTI_KBOARD.
src/frame.c (make_terminal_frame): Initialize f->kboard.
src/keyboard.c (cmd_error_internal): Don't kill Emacs if a Quit was
pressed on the tty of a X+tty session.
(read_avail_input): Initialize nread to zero. Abort if there is no
tty after a termcap read.
(interrupt_signal)[USG]: Always reset signal handler.
(init_keyboard): Always set signal handler for SIGINT/SIGQUIT if
noninteractive.
src/term.c (term_dummy_init): Initialize kboard to the initial_kboard.
(term_init): Free component structures of the initial tty. Clear xmalloced structures.
Moved rif initialization to syms_of_term.
(term_init)[MULTI_KBOARD]: Initialize tty->kboard.
(delete_tty)[MULTI_KBOARD]: Delete the keyboard.
(syms_of_term): Initialize tty_display_method_template.
src/termchar.h (tty_output)[MULTI_KBOARD]: Added kboard member.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-31
author | Karoly Lorentey <lorentey@elte.hu> |
---|---|
date | Fri, 02 Jan 2004 02:54:17 +0000 |
parents | 2ecd1f669db9 |
children | 5de4189e659d |
files | README.multi-tty lib-src/emacsclient.c src/.gdbinit src/config.in src/frame.c src/frame.h src/keyboard.c src/keyboard.h src/term.c src/termchar.h |
diffstat | 10 files changed, 213 insertions(+), 120 deletions(-) [+] |
line wrap: on
line diff
--- a/README.multi-tty Fri Jan 02 01:15:26 2004 +0000 +++ b/README.multi-tty Fri Jan 02 02:54:17 2004 +0000 @@ -6,6 +6,22 @@ multiple, different tty devices and simultaneous X and tty frames from a single Emacs session. +Some use cases: + +Emacs is notoriously slow at startup, so most people use another +editor or emacsclient for quick editing jobs from the console. +Unfortunately, emacsclient was very awkward to use, because it did not +support opening a new Emacs frame on the current virtual console. +Now, with multi-tty support, it can do that. (Emacsclient starts up +faster than vi!) + +Some Gnus users (including me) run Gnus in an X frame in its own Emacs +instance, which they typically leave running for weeks. It would be +nice if they could connect to this instance from a remote ssh session +and check their messages without opening a remote X frame or resorting +to gnus-slave. + + WHO IS DOING IT --------------- @@ -18,46 +34,66 @@ tla register-archive lorentey@elte.hu--2004 http://lorentey.web.elte.hu/arch/2004/ tla get lorentey@elte.hu--2004/emacs--multi-tty <directory> -(I use tla 1.1.) +(I use a recent arch development snapshot, but any of the released +versions of arch will do fine, I think.) +If you don't have arch, the branch has a homepage from which you can +download conventional patches against Emacs CVS HEAD: + + http://lorentey.web.elte.hu/project/emacs.html STATUS ------ -Basic multi-tty support is there; there are some rough edges, but it -already seems to be usable. Emacsclient has been extended to support -opening a new terminal frame. +Multi-tty support is stable, I think most of the problems were fixed. +(It still needs testing on other architectures, though.) Please let +me know if you find any bugs in it. Emacsclient has been extended to +support opening a new terminal frame. -To try it out, compile the multi-tty branch with the following +To try it out, compile and run the multi-tty branch with the following commands: mkdir +build cd +build ../configure make bootstrap + src/emacs -nw + M-x server-start -then start up the emacs server (src/emacs -nw, M-x server-start), and -then (from a shell prompt on another terminal) start emacsclient with +and then (from a shell prompt on another terminal) start emacsclient +with - lib-src/emacsclient -f /optional/file/names... + lib-src/emacsclient -t /optional/file/names... You'll hopefully have two fully working, independent frames on -separate terminals. (This seems to be very useful, emacsclient starts -up even faster than vi!) :-) You can close the newly opened frame and -return to the shell without exiting Emacs by pressing C-x 5 0, i.e., -delete-frame. Creating new frames on the same tty with C-x 5 2 -works exactly as before. Suspending Emacs is disabled at the moment. -If you exit emacs, all terminals should be restored to their previous -states. +separate terminals. The new frame is closed automatically when you +have finished editing the specified files (C-x #), but delete-frame +(C-x 5 0) also works. Of course, you can create frames on more than +two tty devices. + +Creating new frames on the same tty with C-x 5 2 works, and they +behave the same way as in previous Emacs versions. If you exit emacs, +all terminals should be restored to their previous states. + +This is work in progress, and probably full of bugs. You should +always run emacs from gdb, so that you'll have a live instance to +debug if something goes wrong. Please send me your reports. -X support is (I hope) working, but at the moment there are problems -with simultaneous X and tty devices, so don't do that. +Problems: + + * Suspending Emacs is disabled if there are multiple tty + devices. Also, there is no way to suspend emacsclient. This + will be fixed. -Mac, Windows and DOS support is broken, probably doesn't even -compile -- this will be solved later. + * X support is (I hope) working, but at the moment there are + problems with simultaneous X and tty devices, so don't do + that - start a separate Emacs with -nw and run the server + there. -Only tested on my GNU/Linux box. + * Mac, Windows and DOS support is broken, probably doesn't + even compile -- this will be solved later. + * Only tested on my GNU/Linux box. NEWS ---- @@ -88,6 +124,78 @@ See arch logs. +THINGS TO DO +------------ + +** Fix rif issue with X-tty combo sessions. IMHO the best thing to do + is to get rid of that global variable (and use the value value in + display_method, which is guaranteed to be correct). + +** Fix faces on tty frames during X-tty combo sessions. + +** During an X-tty combo session, a (message "Hello") from a tty frame + goes to the X frame. Fix this. + +** Find out the best way to support suspending Emacs with multiple + ttys. My guess: disable it on the controlling tty, but from other + ttys pass it on to emacsclient somehow. (It is (I hope) trivial to + extend emacsclient to handle suspend/resume. A `kill -STOP' almost + works right now.) + +** Move baud_rate to tty_output. + +** Do tty output through term_hooks, like graphical display backends. + +** Implement support for starting an interactive Emacs session without + an initial frame. (The user would connect to it and open frames + later, with emacsclient.) Not necessarily a good idea. + +** Fix input from raw ttys (again). + +** Fix Mac support (I can't do this myself). + +** Fix W32 support (I can't do this myself). + +** Fix DOS support (I can't do this myself). + +** Do a grep on XXX and ?? for more issues. + +** Understand Emacs's low-level input system (it seems complicated) :-) + +** What does interrupt_input do? I tried to disable it for raw + secondary tty support, but it does not seem to do anything useful. + (Update: Look again. X unconditionally enables this, maybe that's + why raw terminal support is broken again. I really do need to + understand input.) + +** Make sure C-g goes to the right frame. This is hard, as SIGINT + doesn't have a tty parameter. :-( + +** I have seen a case when Emacs with multiple ttys fell into a loop + eating 100% of CPU time. Strace showed this loop: + + getpid() = 30284 + kill(30284, SIGIO) = 0 + --- SIGIO (I/O possible) @ 0 (0) --- + ioctl(6, FIONREAD, [0]) = -1 EIO (Input/output error) + ioctl(5, FIONREAD, [0]) = -1 EIO (Input/output error) + ioctl(0, FIONREAD, [0]) = 0 + sigreturn() = ? (mask now []) + gettimeofday({1072842297, 747760}, NULL) = 0 + gettimeofday({1072842297, 747806}, NULL) = 0 + select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0}) + select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0}) + gettimeofday({1072842297, 748245}, NULL) = 0 + + I have not been able to reproduce this. + +** Define a output_initial value for output_method for the initial + frame that is dumped with Emacs. Checking for this frame (e.g. in + cmd_error_internal) is ugly. + +** emacsclient -t from an Emacs term buffer does not work, complains + about face problems. This can even lock up Emacs (if the recursive + frame sets single_kboard). DIARY OF CHANGES ---------------- @@ -222,7 +330,7 @@ (Done, nothing to do. It seems that Emacs does not receive SIGHUP from secondary ttys, which is actually a good thing.) (Update: I - think it would be a bad idea to remove server-frames anyway.) + think it would be a bad idea to remove server-frames.) -- Change emacsclient/server.el to support the -t argument better, i.e. automatically close the socket when the frame is closed. @@ -316,75 +424,10 @@ the point of being unusable. The rif variable causes constant core dumps. Handling input is indeed tricky.) -THINGS TO DO ------------- - -** Fix rif issue with X-tty combo sessions. IMHO the best thing to do - is to get rid of that global variable (and use the value value in - display_method, which is guaranteed to be correct). - -** Fix faces on tty frames during X-tty combo sessions. - -** Find out the best way to support suspending Emacs with multiple - ttys. My guess: disable it on the controlling tty, but from other - ttys pass it on to emacsclient somehow. (It is (I hope) trivial to - extend emacsclient to handle suspend/resume. A `kill -STOP' almost - works right now.) - -** Move baud_rate to tty_output. - -** Do tty output through term_hooks, like graphical display backends. - -** Implement support for starting an interactive Emacs session without - an initial frame. (The user would connect to it and open frames - later, with emacsclient.) Not necessarily a good idea. - -** Fix input from raw ttys (again). - -** Fix Mac support (I can't do this myself). - -** Fix W32 support (I can't do this myself). - -** Fix DOS support (I can't do this myself). - -** Do a grep on XXX and ?? for more issues. +-- Rewrite multi-tty input in terms of MULTI_KBOARD. -** Understand Emacs's low-level input system (it seems complicated) - :-) and maybe rewrite multi-tty input in terms of MULTI_KBOARD. - (Update: This backtrace from a tty-X combo session hints that this - may be necessary.) - - #0 abort () at /home/lorentey/work/emacs/emacs--multi-tty/src/emacs.c:417 - #1 0x081104fb in read_char (commandflag=0, nmaps=0, maps=0x0, prev_event=675499188, used_mouse_menu=0x0) at /home/lorentey/work/emacs/emacs--multi-tty/src/keyboard.c:2581 - #2 0x0819f23e in read_filtered_event (no_switch_frame=1, ascii_required=0, error_nonascii=0, input_method=0) at /home/lorentey/work/emacs/emacs--multi-tty/src/lread.c:468 - #3 0x0819387c in Fy_or_n_p (prompt=1759896324) at /home/lorentey/work/emacs/emacs--multi-tty/src/fns.c:3115 - ... - -** What does interrupt_input do? I tried to disable it for raw - secondary tty support, but it does not seem to do anything useful. - (Update: Look again. X unconditionally enables this, maybe that's - why raw terminal support is broken again. I really do need to - understand input.) - -** Make sure C-g goes to the right frame. This is hard, as SIGINT - doesn't have a tty parameter. :-( - -** I have seen a case when Emacs with multiple ttys fell into a loop - eating 100% of CPU time. Strace showed this loop: - - getpid() = 30284 - kill(30284, SIGIO) = 0 - --- SIGIO (I/O possible) @ 0 (0) --- - ioctl(6, FIONREAD, [0]) = -1 EIO (Input/output error) - ioctl(5, FIONREAD, [0]) = -1 EIO (Input/output error) - ioctl(0, FIONREAD, [0]) = 0 - sigreturn() = ? (mask now []) - gettimeofday({1072842297, 747760}, NULL) = 0 - gettimeofday({1072842297, 747806}, NULL) = 0 - select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0}) - select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0}) - gettimeofday({1072842297, 748245}, NULL) = 0 - - I have not been able to reproduce this. + (Done. In fact, there was no need to rewrite anything, I just + added a kboard member to tty_display_info, and initialized the + frame's kboard from there.) ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
--- a/lib-src/emacsclient.c Fri Jan 02 01:15:26 2004 +0000 +++ b/lib-src/emacsclient.c Fri Jan 02 02:54:17 2004 +0000 @@ -794,7 +794,7 @@ { do { res = read (fileno (in), string, BUFSIZ-1); - } while (res == EINTR); + } while (res < 0 && errno == EINTR); if (res < 0) { reset_tty ();
--- a/src/.gdbinit Fri Jan 02 01:15:26 2004 +0000 +++ b/src/.gdbinit Fri Jan 02 02:54:17 2004 +0000 @@ -383,7 +383,7 @@ show environment DISPLAY show environment TERM -set args -geometry 80x40+0+0 +#set args -geometry 80x40+0+0 # Don't let abort actually run, as it will make # stdio stop working and therefore the `pr' command above as well.
--- a/src/config.in Fri Jan 02 01:15:26 2004 +0000 +++ b/src/config.in Fri Jan 02 02:54:17 2004 +0000 @@ -863,6 +863,12 @@ #define HAVE_MOUSE #endif +/* Multi-tty support relies on MULTI_KBOARD. It seems safe to turn it + on unconditionally. */ +#ifndef MULTI_KBOARD +#define MULTI_KBOARD +#endif + /* Define USER_FULL_NAME to return a string that is the user's full name. It can assume that the variable `pw'
--- a/src/frame.c Fri Jan 02 01:15:26 2004 +0000 +++ b/src/frame.c Fri Jan 02 02:54:17 2004 +0000 @@ -488,6 +488,7 @@ char name[20]; #ifdef MULTI_KBOARD + /* Create the initial keyboard. */ if (!initial_kboard) { initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); @@ -567,6 +568,9 @@ } FRAME_TTY (f)->reference_count++; f->display_method = FRAME_TTY (f)->display_method; +#ifdef MULTI_KBOARD + f->kboard = FRAME_TTY (f)->kboard; +#endif } #ifdef CANNOT_DUMP
--- a/src/frame.h Fri Jan 02 01:15:26 2004 +0000 +++ b/src/frame.h Fri Jan 02 02:54:17 2004 +0000 @@ -292,8 +292,10 @@ #ifdef MULTI_KBOARD /* A pointer to the kboard structure associated with this frame. - For termcap frames, this points to initial_kboard. For X frames, - it will be the same as display.x->display_info->kboard. */ + For termcap frames, it will be the same as + output_data.tty->display_info->kboard. + For X frames, it will be the same as + output_data.x->display_info->kboard. */ struct kboard *kboard; #endif
--- a/src/keyboard.c Fri Jan 02 01:15:26 2004 +0000 +++ b/src/keyboard.c Fri Jan 02 02:54:17 2004 +0000 @@ -1205,7 +1205,8 @@ running under a window system. */ || (!NILP (Vwindow_system) && !inhibit_window_system - && FRAME_TERMCAP_P (sf)) + && FRAME_TERMCAP_P (sf) + && !FRAME_TTY (sf)->type) /* XXX This is ugly. */ || noninteractive) { stream = Qexternal_debugging_output; @@ -6594,7 +6595,7 @@ { struct input_event buf[KBD_BUFFER_SIZE]; register int i; - int nread; + int nread = 0; for (i = 0; i < KBD_BUFFER_SIZE; i++) EVENT_INIT (buf[i]); @@ -6738,10 +6739,13 @@ #endif /* not MSDOS */ #endif /* not WINDOWSNT */ + if (!tty) + abort (); + /* Select frame corresponding to the active tty. Note that the value of selected_frame is not reliable here, redisplay tends to temporarily change it. But tty should always be non-NULL. */ - frame = (tty ? tty->top_frame : selected_frame); + frame = tty->top_frame; for (i = 0; i < nread; i++) { @@ -10245,13 +10249,10 @@ struct frame *sf = SELECTED_FRAME (); #if defined (USG) && !defined (POSIX_SIGNALS) - if (!read_socket_hook && NILP (Vwindow_system)) - { - /* USG systems forget handlers when they are used; - must reestablish each time */ - signal (SIGINT, interrupt_signal); - signal (SIGQUIT, interrupt_signal); - } + /* USG systems forget handlers when they are used; + must reestablish each time */ + signal (SIGINT, interrupt_signal); + signal (SIGQUIT, interrupt_signal); #endif /* USG */ cancel_echoing (); @@ -10626,7 +10627,7 @@ wipe_kboard (current_kboard); init_kboard (current_kboard); - if (!noninteractive && !read_socket_hook && NILP (Vwindow_system)) + if (!noninteractive) { signal (SIGINT, interrupt_signal); #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
--- a/src/keyboard.h Fri Jan 02 01:15:26 2004 +0000 +++ b/src/keyboard.h Fri Jan 02 02:54:17 2004 +0000 @@ -21,7 +21,7 @@ /* Length of echobuf field in each KBOARD. */ /* Each KBOARD represents one logical input stream from which Emacs gets input. - If we are using an ordinary terminal, it has one KBOARD object. + If we are using ordinary terminals, it has one KBOARD object for each terminal device. Usually each X display screen has its own KBOARD, but when two of them are on the same X server, we assume they share a keyboard and give them one KBOARD in common. @@ -152,7 +152,7 @@ }; #ifdef MULTI_KBOARD -/* Temporarily used before a frame has been opened, and for termcap frames */ +/* Temporarily used before a frame has been opened. */ extern KBOARD *initial_kboard; /* In the single-kboard state, this is the kboard
--- a/src/term.c Fri Jan 02 01:15:26 2004 +0000 +++ b/src/term.c Fri Jan 02 02:54:17 2004 +0000 @@ -2189,6 +2189,7 @@ tty_list->output = stdout; tty_list->Wcm = (struct cm *) xmalloc (sizeof (struct cm)); tty_list->display_method = (struct display_method *) xmalloc (sizeof (struct display_method)); + tty_list->kboard = initial_kboard; return tty_list; } @@ -2212,6 +2213,15 @@ the dummy terminal created for the initial frame. */ if (tty->type) return tty; + + /* Free up temporary structures. */ + if (tty->Wcm) + xfree (tty->Wcm); + if (tty->display_method) + xfree (tty->display_method); + if (tty->kboard != initial_kboard) + abort (); + tty->kboard = 0; } else { @@ -2221,20 +2231,18 @@ tty_list = tty; } - if (! tty->Wcm) - tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm)); - - if (! tty->display_method) - tty->display_method = (struct display_method *) xmalloc (sizeof (struct display_method)); + tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm)); + Wcm_clear (tty); + + /* Each termcap frame has its own display method. */ + tty->display_method = (struct display_method *) xmalloc (sizeof (struct display_method)); + bzero (tty->display_method, sizeof (struct display_method)); /* Initialize the common members in the new display method with our predefined template. */ *tty->display_method = tty_display_method_template; f->display_method = tty->display_method; - /* Termcap-based displays don't support window-based redisplay. */ - f->display_method->rif = 0; - /* Make sure the frame is live; if an error happens, it must be deleted. */ f->output_method = output_termcap; @@ -2278,7 +2286,7 @@ FrameCols (tty) = FRAME_COLS (f); tty->specified_window = FRAME_LINES (f); - f->display_method->delete_in_insert_mode = 1; + tty->display_method->delete_in_insert_mode = 1; UseTabs (tty) = 0; FRAME_SCROLL_REGION_OK (f) = 0; @@ -2509,7 +2517,7 @@ } #if 0 /* This is not used anywhere. */ - f->display_method->min_padding_speed = tgetnum ("pb"); + tty->display_method->min_padding_speed = tgetnum ("pb"); #endif TabWidth (tty) = tgetnum ("tw"); @@ -2723,6 +2731,19 @@ FRAME_CHAR_INS_DEL_OK (f) = 0; #endif +#ifdef MULTI_KBOARD + tty->kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); + init_kboard (tty->kboard); + tty->kboard->next_kboard = all_kboards; + all_kboards = tty->kboard; + /* Don't let the initial kboard remain current longer than necessary. + That would cause problems if a file loaded on startup tries to + prompt in the mini-buffer. */ + if (current_kboard == initial_kboard) + current_kboard = tty->kboard; + tty->kboard->reference_count++; +#endif + /* Don't do this. I think termcap may still need the buffer. */ /* xfree (buffer); */ @@ -2735,7 +2756,7 @@ tty_set_terminal_modes (tty); return tty; -#endif /* WINDOWSNT */ +#endif /* not WINDOWSNT */ } /* VARARGS 1 */ @@ -2844,6 +2865,13 @@ if (tty->display_method) xfree (tty->display_method); +#ifdef MULTI_KBOARD + if (tty->kboard && --tty->kboard->reference_count > 0) + abort (); + if (tty->kboard) + delete_kboard (tty->kboard); +#endif + bzero (tty, sizeof (struct tty_display_info)); xfree (tty); deleting_tty = 0; @@ -2897,9 +2925,13 @@ defsubr (&Sframe_tty_type); defsubr (&Sdelete_tty); - /* XXX tty_display_method_template initialization will go here. */ - Fprovide (intern ("multi-tty"), Qnil); + + /* Initialize the display method template. */ + + /* Termcap-based displays don't support window-based redisplay. */ + tty_display_method_template.rif = 0; + }
--- a/src/termchar.h Fri Jan 02 01:15:26 2004 +0000 +++ b/src/termchar.h Fri Jan 02 02:54:17 2004 +0000 @@ -182,6 +182,11 @@ /* This is a copy of struct frame's display_method value; needed for freeing up memory when deleting the tty. */ struct display_method *display_method; + +#ifdef MULTI_KBOARD + /* The terminal's keyboard object. */ + struct kboard *kboard; +#endif }; /* A chain of structures for all tty devices currently in use. */