changeset 82987:1682917e56b4

Major bugfixes and slight enhancements. src/dispextern.h (get_tty_size, tabs_safe_p, init_baud_rate): Update prototypes. src/dispnew.c (window_change_signal): Update call to get_tty_size. src/frame.c (Fmake_terminal_frame): Ditto. src/keyboard.c (Fsuspend_emacs): Ditto. src/sysdep.c: Eliminate tty_outputs, wherever possible. (The exceptions are init_sys_modes and reset_sys_modes, which need access to tty-local parameters). (init_baud_rate): Change tty_output parameter to a simple file descriptor. (narrow_foreground_group, widen_foreground_group): Ditto. (tabs_safe_p, get_tty_size): Ditto. (init_sys_modes): Update narrow_foreground_group invocation. (reset_sys_modes): Update widen_foreground_group invocation. (request_sigio)[!FASYNC && STRIDE]: Fix function signature. src/term.c (delete_tty): Only close output file handle if it is different from input. Re-enable freeing of Wcm. (term_init): Update get_tty_size, tabs_safe_p and init_baud_rate invocations. lib-src/emacsclient.c (here): Renamed to frame. (longopts): Change --here to --frame. The -h short option may be confused with --help. (decode_options, print_help_and_exit): Update to reflect above changes. (main): Ditto. lisp/server.el (server-start): Fix frame-live-p call syntax. (server-process-filter): Handle 'emacsclient -f' without file arguments. Don't return any values to emacsclient when 'emacsclient -f -e'. (server-switch-buffer): Prevent infinite recursion when there are no files to edit. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-27
author Karoly Lorentey <lorentey@elte.hu>
date Tue, 30 Dec 2003 19:27:57 +0000
parents 02a346f99eaf
children f82e3a6f5ccb
files README.multi-tty lib-src/emacsclient.c lisp/server.el src/dispextern.h src/dispnew.c src/frame.c src/keyboard.c src/sysdep.c src/term.c
diffstat 9 files changed, 85 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Tue Dec 30 17:51:52 2003 +0000
+++ b/README.multi-tty	Tue Dec 30 19:27:57 2003 +0000
@@ -39,7 +39,7 @@
 then start up the emacs server (src/emacs, M-x server-start), and then
 (from a shell prompt on another terminal) start emacsclient with
 
-	lib-src/emacsclient -h  /optional/file/names...
+	lib-src/emacsclient -f /optional/file/names...
 
 You'll hopefully have two fully working, independent frames on
 separate terminals.  (This seems to be very useful, emacsclient starts
@@ -213,13 +213,7 @@
 
    (Seems to be working OK.)
 
-THINGS TO DO
-------------
-
-** Understand Emacs's low-level input system.  It seems
-   complicated. :-)
-
-** Fix mysterious memory corruption error with tty deletion.  To
+-- Fix mysterious memory corruption error with tty deletion.  To
    trigger it, try the following shell command:
 
 	while true; do TERM=no-such-terminal-definition emacsclient -h; done
@@ -230,17 +224,23 @@
    Why were these vars collected into a struct before multi-tty
    support?)
 
-   The bug does not seem to happen if the error occurs before terminal
-   initialization or if I comment out all xfree()s in delete_frame.
-   Update: yes it does, although it is much rarer.  Or maybe it's
-   another bug.
+   (Done.  Whew.  It turned out that the problem had nothing to do
+   with hypothetical external references to Wcm, or any other
+   tty_output component; it was simply that delete_tty closed the
+   filehandles of secondary ttys twice, resulting in fclose doubly
+   free()ing memory.  Utterly trivial matter.  I love the C's memory
+   management, it puts hair on your chest.)
 
-   Idea: Some of these errors may have been caused by having more
-   file handles than FD_SETSIZE.
+THINGS TO DO
+------------
+
+** Understand Emacs's low-level input system (it seems complicated) :-)
+   and maybe rewrite multi-tty input in terms of MULTIKBOARD.
 
 ** Find out why does Emacs abort when it wants to close its
    controlling tty.  Hint: chan_process[] array.  Hey, maybe
-   noninterrupt-IO would work, too?
+   noninterrupt-IO would work, too?  Update: no, there is no process
+   for stdin/out.
 
 ** Support raw secondary terminals.  (Note that SIGIO works only on
    the controlling terminal.) Hint: extend read_input_waiting() for
@@ -252,9 +252,21 @@
 ** Issue with SIGIO: it needs to be disabled during redisplay.  See if
    fcntl() kernel behaviour could be emulated by emacsclient.
 
+** Get rid of the accessor macros in termchar.h, or define macros for
+   all members.
+
 ** Make parts of struct tty_output accessible from Lisp.  The device
    name and the type is sufficient.
 
+** server.el: There are issues with saving files in buffers of closed
+   clients.  Try editing a file with emacsclient -f, and (without
+   saving it) do a delete-frame.  The frame is closed without
+   question, and a surprising confirmation prompt appears in another
+   frame.
+
+** emacsclient.el, server.el: Handle eval or file open errors when
+   doing -f.
+
 ** Export delete_tty to the Lisp environment, for emacsclient.
 
 ** Make sure C-g goes to the right frame.  This is hard, as SIGINT
@@ -283,6 +295,6 @@
 
 ** Fix DOS support (I can't do this myself).
 
-
+** Do a grep on XXX and ?? for more issues.
 
 ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
--- a/lib-src/emacsclient.c	Tue Dec 30 17:51:52 2003 +0000
+++ b/lib-src/emacsclient.c	Tue Dec 30 19:27:57 2003 +0000
@@ -118,7 +118,7 @@
 char *display = NULL;
 
 /* Nonzero means open a new Emacs frame on the current terminal. */
-int here = 0;
+int frame = 0;
 
 /* If non-NULL, the name of an editor to fallback to if the server
    is not running.  --alternate-editor.   */
@@ -135,7 +135,7 @@
   { "eval",	no_argument,	   NULL, 'e' },
   { "help",	no_argument,	   NULL, 'H' },
   { "version",	no_argument,	   NULL, 'V' },
-  { "here",	no_argument,       NULL, 'h' },
+  { "frame",	no_argument,       NULL, 'f' },
   { "alternate-editor", required_argument, NULL, 'a' },
   { "socket-name",	required_argument, NULL, 's' },
   { "display",	required_argument, NULL, 'd' },
@@ -153,7 +153,7 @@
   while (1)
     {
       int opt = getopt_long (argc, argv,
-			     "VHnea:s:d:h", longopts, 0);
+			     "VHnea:s:d:f", longopts, 0);
 
       if (opt == EOF)
 	break;
@@ -192,8 +192,8 @@
 	  exit (0);
 	  break;
 
-        case 'h':
-          here = 1;
+        case 'f':
+          frame = 1;
           break;
           
 	case 'H':
@@ -207,7 +207,7 @@
 	}
     }
 
-  if (here) {
+  if (frame) {
     nowait = 0;
     display = 0;
   }
@@ -225,7 +225,7 @@
 The following OPTIONS are accepted:\n\
 -V, --version           Just print a version info and return\n\
 -H, --help              Print this usage information message\n\
--h, --here              Open a new Emacs frame on the current terminal\n\
+-f, --frame             Open a new Emacs frame on the current terminal\n\
 -n, --no-wait           Don't wait for the server to return\n\
 -e, --eval              Evaluate the FILE arguments as ELisp expressions\n\
 -d, --display=DISPLAY   Visit the file in the given display\n\
@@ -876,7 +876,7 @@
   /* Process options.  */
   decode_options (argc, argv);
 
-  if ((argc - optind < 1) && !eval && !here)
+  if ((argc - optind < 1) && !eval && !frame)
     {
       fprintf (stderr, "%s: file name or argument required\n", progname);
       fprintf (stderr, "Try `%s --help' for more information\n", progname);
@@ -1048,7 +1048,7 @@
       fprintf (out, " ");
     }
 
-  if (here)
+  if (frame)
     {
       if (! init_signals ())
         {
@@ -1108,7 +1108,7 @@
     }
   else
     {
-      if (!here)
+      if (!frame)
         {
           while ((str = fgets (string, BUFSIZ, stdin)))
             {
@@ -1128,7 +1128,7 @@
       return 0;
     }
 
-  if (here)
+  if (frame)
     {
       if (! pty_conversation (out))
         {
--- a/lisp/server.el	Tue Dec 30 17:51:52 2003 +0000
+++ b/lisp/server.el	Tue Dec 30 19:27:57 2003 +0000
@@ -271,7 +271,7 @@
   (while server-frames
     (let ((frame (cadar server-frames)))
       (setq server-frames (cdr server-frames))
-      (when frame-live-p frame (delete-frame frame 'force))))
+      (when (frame-live-p frame) (delete-frame frame 'force))))
   (unless leave-dead
     (if server-process
 	(server-log (message "Restarting server")))
@@ -314,7 +314,7 @@
 	  (coding-system (and default-enable-multibyte-characters
 			      (or file-name-coding-system
 				  default-file-name-coding-system)))
-	  client nowait eval
+	  client nowait eval newframe
 	  (files nil)
 	  (lineno 1)
 	  (columnno 0))
@@ -336,6 +336,7 @@
 		       (setq request "")))))
 	   ;; Open a new frame at the client.  ARG is the name of the pseudo tty.
 	   ((and (equal "-pty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
+	    (setq newframe t)
 	    (let ((pty (server-unquote-arg (match-string 1 request)))
 		  (type (server-unquote-arg (match-string 2 request))))
 	      (setq request (substring request (match-end 0)))
@@ -364,7 +365,7 @@
 	    (if eval
 		(condition-case err
 		    (let ((v (eval (car (read-from-string arg)))))
-		      (when v
+		      (when (and (not newframe v))
 			(with-temp-buffer
 			  (let ((standard-output (current-buffer)))
 			    (pp v)
@@ -382,7 +383,7 @@
 	(server-visit-files files client nowait)
 	(run-hooks 'post-command-hook))
       ;; CLIENT is now a list (CLIENTNUM BUFFERS...)
-      (if (null (cdr client))
+      (if (and (not newframe) (null (cdr client)))
 	  ;; This client is empty; get rid of it immediately.
 	  (progn
 	    (let ((frame (assq (car client) server-frames)))
@@ -607,7 +608,8 @@
   ;; since we've already effectively done that.
   (if (null next-buffer)
       (if server-clients
-	  (server-switch-buffer (nth 1 (car server-clients)) killed-one)
+	  (let ((buffer (nth 1 (car server-clients))))
+	    (and buffer (server-switch-buffer buffer killed-one)))
 	(unless (or killed-one (window-dedicated-p (selected-window)))
 	  (switch-to-buffer (other-buffer))
 	  (message "No server buffers remain to edit")))
--- a/src/dispextern.h	Tue Dec 30 17:51:52 2003 +0000
+++ b/src/dispextern.h	Tue Dec 30 19:27:57 2003 +0000
@@ -2562,11 +2562,11 @@
 
 /* Defined in sysdep.c */
 
-void get_tty_size P_ ((struct tty_output *, int *, int *));
+void get_tty_size P_ ((int, int *, int *));
 void request_sigio P_ ((void));
 void unrequest_sigio P_ ((void));
-int tabs_safe_p P_ ((struct tty_output *));
-void init_baud_rate P_ ((struct tty_output *));
+int tabs_safe_p P_ ((int));
+void init_baud_rate P_ ((int));
 void init_sigio P_ ((int));
 
 /* Defined in xfaces.c */
--- a/src/dispnew.c	Tue Dec 30 17:51:52 2003 +0000
+++ b/src/dispnew.c	Tue Dec 30 19:27:57 2003 +0000
@@ -5927,7 +5927,7 @@
     if (! tty->term_initted)
       continue;
     
-    get_tty_size (tty, &width, &height);
+    get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
     
     {
       Lisp_Object tail, frame;
--- a/src/frame.c	Tue Dec 30 17:51:52 2003 +0000
+++ b/src/frame.c	Tue Dec 30 19:27:57 2003 +0000
@@ -656,7 +656,7 @@
 
   {
     int width, height;
-    get_tty_size (FRAME_TTY (f), &width, &height);
+    get_tty_size (fileno (TTY_INPUT (FRAME_TTY (f))), &width, &height);
     change_frame_size (f, height, width, 0, 0, 0);
   }
   
--- a/src/keyboard.c	Tue Dec 30 17:51:52 2003 +0000
+++ b/src/keyboard.c	Tue Dec 30 19:27:57 2003 +0000
@@ -10127,7 +10127,7 @@
     call1 (Vrun_hooks, intern ("suspend-hook"));
 
   GCPRO1 (stuffstring);
-  get_tty_size (CURTTY (), &old_width, &old_height);
+  get_tty_size (fileno (TTY_INPUT (CURTTY ())), &old_width, &old_height);
   reset_all_sys_modes ();
   /* sys_suspend can get an error if it tries to fork a subshell
      and the system resources aren't available for that.  */
@@ -10143,7 +10143,7 @@
   /* Check if terminal/window size has changed.
      Note that this is not useful when we are running directly
      with a window system; but suspend should be disabled in that case.  */
-  get_tty_size (CURTTY (), &width, &height);
+  get_tty_size (fileno (TTY_INPUT (CURTTY ())), &width, &height);
   if (width != old_width || height != old_height)
     change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
 
--- a/src/sysdep.c	Tue Dec 30 17:51:52 2003 +0000
+++ b/src/sysdep.c	Tue Dec 30 19:27:57 2003 +0000
@@ -309,10 +309,13 @@
 #endif /* not WINDOWSNT */
 }
 
+
 #ifdef SIGTSTP
 
 /* Arrange for character C to be read as the next input from
-   the terminal.  */
+   the terminal.
+   XXX What if we have multiple ttys?
+*/
 
 void
 stuff_char (char c)
@@ -331,7 +334,7 @@
 #endif /* SIGTSTP */
 
 void
-init_baud_rate (struct tty_output *tty)
+init_baud_rate (int fd)
 {
   if (noninteractive)
     emacs_ospeed = 0;
@@ -346,7 +349,7 @@
 #ifdef VMS
       struct sensemode sg;
 
-      SYS$QIOW (0, fileno (TTY_INPUT (tty)), IO$_SENSEMODE, &sg, 0, 0,
+      SYS$QIOW (0, fd, IO$_SENSEMODE, &sg, 0, 0,
 		&sg.class, 12, 0, 0, 0, 0 );
       emacs_ospeed = sg.xmit_baud;
 #else /* not VMS */
@@ -354,7 +357,7 @@
       struct termios sg;
 
       sg.c_cflag = B9600;
-      tcgetattr (fileno (TTY_INPUT (tty)), &sg);
+      tcgetattr (fd, &sg);
       emacs_ospeed = cfgetospeed (&sg);
 #if defined (USE_GETOBAUD) && defined (getobaud)
       /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
@@ -367,16 +370,16 @@
 
       sg.c_cflag = B9600;
 #ifdef HAVE_TCATTR
-      tcgetattr (fileno (TTY_INPUT (tty)), &sg);
+      tcgetattr (fd, &sg);
 #else
-      ioctl (fileno (TTY_INPUT (tty)), TCGETA, &sg);
+      ioctl (fd, TCGETA, &sg);
 #endif
       emacs_ospeed = sg.c_cflag & CBAUD;
 #else /* neither VMS nor TERMIOS nor TERMIO */
       struct sgttyb sg;
 
       sg.sg_ospeed = B9600;
-      if (ioctl (fileno (TTY_INPUT (tty)), TIOCGETP, &sg) < 0)
+      if (ioctl (fd, TIOCGETP, &sg) < 0)
 	abort ();
       emacs_ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
@@ -392,6 +395,7 @@
     baud_rate = 1200;
 }
 
+
 /*ARGSUSED*/
 void
 set_exclusive_use (fd)
@@ -976,7 +980,7 @@
 }
 
 void
-unrequest_sigio (struct tty_output *tty)
+unrequest_sigio ()
 {
   int off = 0;
 
@@ -1078,23 +1082,23 @@
    group, redirect the TTY to point to our own process group.  We need
    to be in our own process group to receive SIGIO properly.  */
 void
-narrow_foreground_group (struct tty_output *tty)
+narrow_foreground_group (int fd)
 {
   int me = getpid ();
 
   setpgrp (0, inherited_pgroup);
   /* XXX This only works on the controlling tty. */
   if (inherited_pgroup != me)
-    EMACS_SET_TTY_PGRP (fileno (TTY_INPUT (tty)), &me);
+    EMACS_SET_TTY_PGRP (fd, &me);
   setpgrp (0, me);
 }
 
 /* Set the tty to our original foreground group.  */
 void
-widen_foreground_group (struct tty_output *tty)
+widen_foreground_group (int fd)
 {
   if (inherited_pgroup != getpid ())
-    EMACS_SET_TTY_PGRP (fileno (TTY_INPUT (tty)), &inherited_pgroup);
+    EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
   setpgrp (0, inherited_pgroup);
 }
 
@@ -1289,11 +1293,9 @@
 void
 init_all_sys_modes (void)
 {
-  struct tty_output *tty = tty_list;
-  while (tty) {
+  struct tty_output *tty;
+  for (tty = tty_list; tty; tty = tty->next)
     init_sys_modes (tty);
-    tty = tty->next;
-  }
 }
 
 void
@@ -1358,7 +1360,7 @@
 
 #ifdef BSD_PGRPS
   if (! read_socket_hook && EQ (Vwindow_system, Qnil))
-    narrow_foreground_group (tty_out);
+    narrow_foreground_group (fileno (TTY_INPUT (tty_out)));
 #endif
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1683,11 +1685,11 @@
    At the time this is called, init_sys_modes has not been done yet.  */
 
 int
-tabs_safe_p (struct tty_output *tty)
+tabs_safe_p (int fd)
 {
   struct emacs_tty etty;
 
-  EMACS_GET_TTY (fileno (TTY_INPUT (tty)), &etty);
+  EMACS_GET_TTY (fd, &etty);
   return EMACS_TTY_TABS_OK (&etty);
 }
 
@@ -1696,9 +1698,7 @@
    We store 0 if there's no valid information.  */
 
 void
-get_tty_size (tty_out, widthp, heightp)
-     struct tty_output *tty_out;
-     int *widthp, *heightp;
+get_tty_size (int fd, int *widthp, int *heightp)
 {
 
 #ifdef TIOCGWINSZ
@@ -1706,7 +1706,7 @@
   /* BSD-style.  */
   struct winsize size;
 
-  if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGWINSZ, &size) == -1)
+  if (ioctl (fd, TIOCGWINSZ, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1720,7 +1720,7 @@
   /* SunOS - style.  */
   struct ttysize size;
 
-  if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGSIZE, &size) == -1)
+  if (ioctl (fd, TIOCGSIZE, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1733,7 +1733,7 @@
 
   struct sensemode tty;
 
-  SYS$QIOW (0, fileno (TTY_INPUT (tty_out)), IO$_SENSEMODE, &tty, 0, 0,
+  SYS$QIOW (0, fd, IO$_SENSEMODE, &tty, 0, 0,
 	    &tty.class, 12, 0, 0, 0, 0);
   *widthp = tty.scr_wid;
   *heightp = tty.scr_len;
@@ -1793,11 +1793,9 @@
 void
 reset_all_sys_modes (void)
 {
-  struct tty_output *tty = tty_list;
-  while (tty) {
+  struct tty_output *tty;
+  for (tty = tty_list; tty; tty = tty->next)
     reset_sys_modes (tty);
-    tty = tty->next;
-  }
 }
 
 /* Prepare the terminal for closing it; move the cursor to the
@@ -1889,7 +1887,7 @@
 #endif
 
 #ifdef BSD_PGRPS
-  widen_foreground_group (tty_out);
+  widen_foreground_group (fileno (TTY_INPUT (tty_out)));
 #endif
 }
 
--- a/src/term.c	Tue Dec 30 17:51:52 2003 +0000
+++ b/src/term.c	Tue Dec 30 19:27:57 2003 +0000
@@ -2403,7 +2403,7 @@
   /* Get frame size from system, or else from termcap.  */
   {
     int height, width;
-    get_tty_size (tty, &width, &height);
+    get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
     FrameCols (tty) = width;
     FrameRows (tty) = height;
   }
@@ -2609,7 +2609,7 @@
               && tty->TS_end_standout_mode
               && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
 
-  UseTabs (tty) = tabs_safe_p (tty) && TabWidth (tty) == 8;
+  UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
 
   TTY_SCROLL_REGION_OK (tty)
     = (tty->Wcm->cm_abs
@@ -2628,7 +2628,7 @@
 
   TTY_FAST_CLEAR_END_OF_LINE (tty) = tty->TS_clr_line != 0;
 
-  init_baud_rate (tty);
+  init_baud_rate (fileno (TTY_INPUT (tty)));
   if (read_socket_hook)		/* Baudrate is somewhat
                                    meaningless in this case */
     baud_rate = 9600;
@@ -2737,7 +2737,7 @@
 
   if (tty->input)
     fclose (tty->input);
-  if (tty->output)
+  if (tty->output && tty->output != tty->input)
     fclose (tty->output);
   if (tty->termscript)
     fclose (tty->termscript);
@@ -2745,10 +2745,8 @@
   if (tty->old_tty)
     xfree (tty->old_tty);
 
-#if 0  /* XXX There is a dangling reference somewhere into this. */
   if (tty->Wcm)
     xfree (tty->Wcm); 
-#endif
   
   bzero (tty, sizeof (struct tty_output));
   xfree (tty);