From f30d612a7a628828baa7c333629a10295605291b Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Fri, 20 Apr 2012 14:39:29 +0800 Subject: [PATCH] Fixes for pty handling in gdb-mi.el and process.c. * lisp/progmodes/gdb-mi.el (gdb): Revert 2012-04-19 change. (gdb-inferior-io--init-proc): New function. (gdb-init-1): Use it. (gdb-inferior-io-sentinel): New sentinel for the gdb-inferior pty, responsible for allocating a new pty and hooking it to gdb when the old pty gets an EIO due to process exit. (gdb-delchar-or-quit): New command. Bind it in gdb-mi buffers. (gdb-tooltip-print): Don't use obsolete tooltip-use-echo-area. (gdb-inferior-io--maybe-delete-pty): Move into gdb-reset. * src/process.c (wait_reading_process_output): If EIO occurs on a pty, set the status to "failed" and ensure that sentinel is run. * doc/lispref/processes.texi (Asynchronous Processes): Mention nil argument to start-process. --- doc/lispref/ChangeLog | 5 +++ doc/lispref/processes.texi | 7 +++- lisp/ChangeLog | 12 +++++++ lisp/progmodes/gdb-mi.el | 69 +++++++++++++++++++++++++------------- src/ChangeLog | 5 +++ src/process.c | 27 +++++++++------ 6 files changed, 91 insertions(+), 34 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 167539aa45..fe555c0458 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,8 @@ +2012-04-20 Chong Yidong + + * processes.texi (Asynchronous Processes): Mention nil argument to + start-process. + 2012-04-20 Glenn Morris * minibuf.texi (Basic Completion): No need to describe obarrays here. diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index cd5647f184..6275ce0b1b 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -559,8 +559,13 @@ already exists, then @var{name} is modified (by appending @samp{<1>}, etc.) to be unique. The buffer @var{buffer-or-name} is the buffer to associate with the process. +If @var{program} is @code{nil}, Emacs opens a new pseudoterminal (pty) +and associates its input and output with @var{buffer-or-name}, without +creating a subprocess. In that case, the remaining arguments +@var{args} are ignored. + The remaining arguments, @var{args}, are strings that specify command -line arguments for the program. +line arguments for the subprocess. In the example below, the first process is started and runs (rather, sleeps) for 100 seconds (the output buffer @samp{foo} is created diff --git a/lisp/ChangeLog b/lisp/ChangeLog index ec008022e0..601e4f4f59 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,15 @@ +2012-04-20 Chong Yidong + + * progmodes/gdb-mi.el (gdb): Revert 2012-04-19 change. + (gdb-inferior-io--init-proc): New function. + (gdb-init-1): Use it. + (gdb-inferior-io-sentinel): New sentinel for the gdb-inferior pty, + responsible for allocating a new pty and hooking it to gdb when + the old pty gets an EIO due to process exit. + (gdb-delchar-or-quit): New command. Bind it in gdb-mi buffers. + (gdb-tooltip-print): Don't use obsolete tooltip-use-echo-area. + (gdb-inferior-io--maybe-delete-pty): Move into gdb-reset. + 2012-04-20 Eli Zaretskii * window.el (window-min-size, window-sizable, window-min-delta) diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 450075fde4..455727f9e0 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -817,10 +817,7 @@ detailed description of this mode. nil 'local) (local-set-key "\C-i" 'completion-at-point) - ;; FIXME: Under some circumstances, `gud-sentinel' apparently does - ;; not get called when the gdb process is killed (Bug#11273). - (add-hook 'post-command-hook 'gdb-inferior-io--maybe-delete-pty - nil t) + (local-set-key [remap comint-delchar-or-maybe-eof] 'gdb-delchar-or-quit) (setq gdb-first-prompt t) (setq gud-running nil) @@ -863,15 +860,8 @@ detailed description of this mode. (gdb-get-buffer-create 'gdb-inferior-io) (gdb-clear-inferior-io) - (set-process-filter (get-process "gdb-inferior") 'gdb-inferior-filter) - (gdb-input - ;; Needs GDB 6.4 onwards - (concat "-inferior-tty-set " - (or - ;; The process can run on a remote host. - (process-get (get-process "gdb-inferior") 'remote-tty) - (process-tty-name (get-process "gdb-inferior")))) - 'ignore) + (gdb-inferior-io--init-proc (get-process "gdb-inferior")) + (if (eq window-system 'w32) (gdb-input "-gdb-set new-console off" 'ignore)) (gdb-input "-gdb-set height 0" 'ignore) @@ -909,6 +899,25 @@ detailed description of this mode. (setq gdb-non-stop nil) (gdb-input "-gdb-set non-stop 0" 'ignore))) +(defun gdb-delchar-or-quit (arg) + "Delete ARG characters or send a quit command to GDB. +Send a quit only if point is at the end of the buffer, there is +no input, and GDB is waiting for input." + (interactive "p") + (unless (and (eq (current-buffer) gud-comint-buffer) + (eq gud-minor-mode 'gdbmi)) + (error "Not in a GDB-MI buffer")) + (let ((proc (get-buffer-process gud-comint-buffer))) + (if (and (eobp) proc (process-live-p proc) + (not gud-running) + (= (point) (marker-position (process-mark proc)))) + ;; Sending an EOF does not work with GDB-MI; submit an + ;; explicit quit command. + (progn + (insert "quit") + (comint-send-input t t)) + (delete-char arg)))) + (defvar gdb-define-alist nil "Alist of #define directives for GUD tooltips.") (defun gdb-create-define-alist () @@ -933,7 +942,6 @@ detailed description of this mode. (push (cons name define) gdb-define-alist)))) (declare-function tooltip-show "tooltip" (text &optional use-echo-area)) -(defvar tooltip-use-echo-area) (defun gdb-tooltip-print (expr) (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer) @@ -941,7 +949,7 @@ detailed description of this mode. (if (re-search-forward ".*value=\\(\".*\"\\)" nil t) (tooltip-show (concat expr " = " (read (match-string 1))) - (or gud-tooltip-echo-area tooltip-use-echo-area + (or gud-tooltip-echo-area (not (display-graphic-p))))))) ;; If expr is a macro for a function don't print because of possible dangerous @@ -1514,13 +1522,26 @@ DOC is an optional documentation string." (gdb-display-buffer (gdb-get-buffer-create 'gdb-inferior-io) t)) -(defun gdb-inferior-io--maybe-delete-pty () - (let ((proc (get-buffer-process gud-comint-buffer)) - (inf-pty (get-process "gdb-inferior"))) - (and (or (null proc) - (memq (process-status proc) '(exit signal))) - inf-pty - (delete-process inf-pty)))) +(defun gdb-inferior-io--init-proc (proc) + ;; Set up inferior I/O. Needs GDB 6.4 onwards. + (set-process-filter proc 'gdb-inferior-filter) + (set-process-sentinel proc 'gdb-inferior-io-sentinel) + (gdb-input + (concat "-inferior-tty-set " + ;; The process can run on a remote host. + (or (process-get proc 'remote-tty) + (process-tty-name proc))) + 'ignore)) + +(defun gdb-inferior-io-sentinel (proc str) + (when (eq (process-status proc) 'failed) + ;; When the debugged process exits, Emacs gets an EIO error on + ;; read from the pty, and stops listening to it. Remove the pty, + ;; make a new one, and pass it to gdb. + (let ((buffer (process-buffer proc))) + ;; `comint-exec' deletes the original process as a side effect. + (comint-exec buffer "gdb-inferior" nil nil nil) + (gdb-inferior-io--init-proc (get-buffer-process buffer))))) (defconst gdb-frame-parameters '((height . 14) (width . 80) @@ -4131,7 +4152,9 @@ This arrangement depends on the value of `gdb-many-windows'." Kills the gdb buffers, and resets variables and the source buffers." ;; The gdb-inferior buffer has a pty hooked up to the main gdb ;; process. This pty must be deleted explicitly. - (gdb-inferior-io--maybe-delete-pty) + (let ((pty (get-process "gdb-inferior"))) + (if pty (delete-process pty))) + ;; Find gdb-mi buffers and kill them. (dolist (buffer (buffer-list)) (unless (eq buffer gud-comint-buffer) (with-current-buffer buffer diff --git a/src/ChangeLog b/src/ChangeLog index 00d257e698..18b6ce1ad6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2012-04-20 Chong Yidong + + * process.c (wait_reading_process_output): If EIO occurs on a pty, + set the status to "failed" and ensure that sentinel is run. + 2012-04-18 Glenn Morris * process.c (Fset_process_inherit_coding_system_flag) diff --git a/src/process.c b/src/process.c index 3ee22d270e..f6f1ad0a6f 100644 --- a/src/process.c +++ b/src/process.c @@ -4893,16 +4893,23 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, It can't hurt. */ else if (nread == -1 && errno == EIO) { - /* Don't do anything if only a pty, with no associated - process (bug#10933). */ - if (XPROCESS (proc)->pid != -2) { - /* Clear the descriptor now, so we only raise the signal - once. */ - FD_CLR (channel, &input_wait_mask); - FD_CLR (channel, &non_keyboard_wait_mask); - - kill (getpid (), SIGCHLD); - } + struct Lisp_Process *p = XPROCESS (proc); + + /* Clear the descriptor now, so we only raise the + signal once. */ + FD_CLR (channel, &input_wait_mask); + FD_CLR (channel, &non_keyboard_wait_mask); + + if (p->pid == -2) + { + /* If the EIO occurs on a pty, sigchld_handler's + wait3() will not find the process object to + delete. Do it here. */ + p->tick = ++process_tick; + p->status = Qfailed; + } + else + kill (getpid (), SIGCHLD); } #endif /* HAVE_PTYS */ /* If we can detect process termination, don't consider the -- 2.20.1