Now on revision 113827. ------------------------------------------------------------ revno: 113827 committer: Xue Fuqiao branch nick: trunk timestamp: Tue 2013-08-13 10:45:12 +0800 message: * doc/lispref/frames.texi (Display Feature Testing): Add indexes. diff: === modified file 'doc/lispref/ChangeLog' --- doc/lispref/ChangeLog 2013-08-13 02:15:57 +0000 +++ doc/lispref/ChangeLog 2013-08-13 02:45:12 +0000 @@ -1,6 +1,6 @@ 2013-08-13 Xue Fuqiao - * frames.texi (Display Feature Testing): Add an index. + * frames.texi (Display Feature Testing): Add indexes. 2013-08-12 Glenn Morris === modified file 'doc/lispref/frames.texi' --- doc/lispref/frames.texi 2013-08-13 02:15:57 +0000 +++ doc/lispref/frames.texi 2013-08-13 02:45:12 +0000 @@ -2403,6 +2403,7 @@ when the question is inapplicable to a certain kind of display. @end defun +@cindex SaveUnder feature @defun display-save-under &optional display This function returns non-@code{nil} if the display supports the SaveUnder feature. That feature is used by pop-up windows === modified file 'lisp/frame.el' --- lisp/frame.el 2013-08-06 10:59:39 +0000 +++ lisp/frame.el 2013-08-13 02:45:12 +0000 @@ -1442,6 +1442,8 @@ (declare-function x-display-backing-store "xfns.c" (&optional terminal)) +;; In NS port, the return value may be `buffered', `retained', or +;; `non-retained'. See src/nsfns.m. (defun display-backing-store (&optional display) "Return the backing store capability of DISPLAY's screen. The value may be `always', `when-mapped', `not-useful', or nil if ------------------------------------------------------------ revno: 113826 committer: Stefan Monnier branch nick: trunk timestamp: Mon 2013-08-12 22:30:52 -0400 message: * lisp/emacs-lisp/timer.el (timer--time-setter): New function. (timer--time): Use it as gv-setter. * lisp/emacs-lisp/gv.el (gv-define-simple-setter): Output warning when setter is not a symbol. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-08-12 17:25:22 +0000 +++ lisp/ChangeLog 2013-08-13 02:30:52 +0000 @@ -1,3 +1,11 @@ +2013-08-13 Stefan Monnier + + * emacs-lisp/timer.el (timer--time-setter): New function. + (timer--time): Use it as gv-setter. + + * emacs-lisp/gv.el (gv-define-simple-setter): Output warning when + setter is not a symbol. + 2013-08-12 Grégoire Jadi * mail/sendmail.el (sendmail-send-it): Don't kill the error buffer @@ -20,8 +28,8 @@ 2013-08-11 Lars Magne Ingebrigtsen - * net/eww.el (eww-display-html): Ignore coding system errors. One - web site uses "utf-8lias" as the coding system. + * net/eww.el (eww-display-html): Ignore coding system errors. + One web site uses "utf-8lias" as the coding system. 2013-08-11 Juanma Barranquero @@ -222,7 +230,7 @@ (allout-up-current-level, allout-end-of-level, allout-reindent-body) (allout-yank-processing, allout-process-exposed) (allout-latex-verb-quote, allout-latexify-one-item, outlineify-sticky) - (allout-latex-verbatim-quote-curr-line): Removed unused variables. + (allout-latex-verbatim-quote-curr-line): Remove unused variables. * emacs-lisp/lisp-mode.el (lisp-eval-defun, last-sexp-toggle-display) (lisp-indent-defform): Mark ignored arguments. (lisp-indent-line): Mark ignored arguments. Remove unused variables. === modified file 'lisp/emacs-lisp/cl-macs.el' --- lisp/emacs-lisp/cl-macs.el 2013-07-12 01:11:22 +0000 +++ lisp/emacs-lisp/cl-macs.el 2013-08-13 02:30:52 +0000 @@ -616,7 +616,7 @@ (declare (debug (form &optional sexp))) (if (cl--compiling-file) (let* ((temp (cl-gentemp "--cl-load-time--")) - (set `(set ',temp ,form))) + (set `(setq ,temp ,form))) (if (and (fboundp 'byte-compile-file-form-defmumble) (boundp 'this-kind) (boundp 'that-one)) (fset 'byte-compile-file-form === modified file 'lisp/emacs-lisp/gv.el' --- lisp/emacs-lisp/gv.el 2013-01-02 16:13:04 +0000 +++ lisp/emacs-lisp/gv.el 2013-08-13 02:30:52 +0000 @@ -217,13 +217,15 @@ temp) so as to preserve the semantics of `setf'." (declare (debug (sexp (&or symbolp lambda-expr) &optional sexp))) + (when (eq 'lambda (car-safe setter)) + (message "Use `gv-define-setter' or name %s's setter function" name)) `(gv-define-setter ,name (val &rest args) ,(if fix-return `(macroexp-let2 nil v val `(progn - (,',setter ,@(append args (list v))) + (,',setter ,@args ,v) ,v)) - `(cons ',setter (append args (list val)))))) + ``(,',setter ,@args ,val)))) ;;; Typical operations on generalized variables. === modified file 'lisp/emacs-lisp/timer.el' --- lisp/emacs-lisp/timer.el 2013-08-10 12:30:38 +0000 +++ lisp/emacs-lisp/timer.el 2013-08-13 02:30:52 +0000 @@ -55,30 +55,29 @@ (defsubst timer--check (timer) (or (timerp timer) (signal 'wrong-type-argument (list #'timerp timer)))) +(defun timer--time-setter (timer time) + (timer--check timer) + (setf (timer--high-seconds timer) (pop time)) + (let ((low time) (usecs 0) (psecs 0)) + (when (consp time) + (setq low (pop time)) + (when time + (setq usecs (pop time)) + (when time + (setq psecs (car time))))) + (setf (timer--low-seconds timer) low) + (setf (timer--usecs timer) usecs) + (setf (timer--psecs timer) psecs) + time)) + ;; Pseudo field `time'. (defun timer--time (timer) + (declare (gv-setter timer--time-setter)) (list (timer--high-seconds timer) (timer--low-seconds timer) (timer--usecs timer) (timer--psecs timer))) -(gv-define-setter timer--time (time timer) - (macroexp-let2 nil val time - `(progn - (timer--check ,timer) - (setf (timer--high-seconds ,timer) (pop ,val)) - (let ((low ,val) (usecs 0) (psecs 0)) - (when (consp ,val) - (setq low (pop ,val)) - (when ,val - (setq usecs (pop ,val)) - (when ,val - (setq psecs (car ,val))))) - (setf (timer--low-seconds ,timer) low) - (setf (timer--usecs ,timer) usecs) - (setf (timer--psecs ,timer) psecs)) - ,val))) - (defun timer-set-time (timer time &optional delta) "Set the trigger time of TIMER to TIME. TIME must be in the internal format returned by, e.g., `current-time'. ------------------------------------------------------------ revno: 113825 committer: Xue Fuqiao branch nick: trunk timestamp: Tue 2013-08-13 10:15:57 +0800 message: * doc/lispref/frames.texi (Display Feature Testing): Add an index. diff: === modified file 'doc/lispref/ChangeLog' --- doc/lispref/ChangeLog 2013-08-12 00:04:15 +0000 +++ doc/lispref/ChangeLog 2013-08-13 02:15:57 +0000 @@ -1,3 +1,7 @@ +2013-08-13 Xue Fuqiao + + * frames.texi (Display Feature Testing): Add an index. + 2013-08-12 Glenn Morris * Makefile.in (prefix, datarootdir, datadir, PACKAGE_TARNAME) === modified file 'doc/lispref/frames.texi' --- doc/lispref/frames.texi 2013-08-10 04:58:31 +0000 +++ doc/lispref/frames.texi 2013-08-13 02:15:57 +0000 @@ -1362,7 +1362,7 @@ @node Input Focus @section Input Focus @cindex input focus -@c @cindex selected frame Duplicates selected-frame +@c @cindex selected frame Duplicates selected-frame, same for selected-window. At any time, one frame in Emacs is the @dfn{selected frame}. The selected window always resides on the selected frame. @@ -2391,6 +2391,7 @@ @code{display-mm-width} in case the system provides incorrect values. @end defopt +@cindex backing store @defun display-backing-store &optional display This function returns the backing store capability of the display. Backing store means recording the pixels of windows (and parts of ------------------------------------------------------------ revno: 113824 fixes bug: http://debbugs.gnu.org/15035 committer: Paul Eggert branch nick: trunk timestamp: Mon 2013-08-12 13:17:32 -0700 message: * process.c (deactivate_process): Reset fds to -1. This fixes a problem introduced by the Bug#15035 patch when using GPG. Reported by Herbert J. Skuhra. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-12 19:48:04 +0000 +++ src/ChangeLog 2013-08-12 20:17:32 +0000 @@ -1,3 +1,9 @@ +2013-08-12 Paul Eggert + + * process.c (deactivate_process): Reset fds to -1 (Bug#15035). + This fixes a problem introduced by the Bug#15035 patch + when using GPG. Reported by Herbert J. Skuhra. + 2013-08-12 Eli Zaretskii * decompress.c [WINDOWSNT]: New static variable. === modified file 'src/process.c' --- src/process.c 2013-08-12 07:12:07 +0000 +++ src/process.c 2013-08-12 20:17:32 +0000 @@ -3842,6 +3842,8 @@ if (inchannel >= 0) { + p->infd = -1; + p->outfd = -1; #ifdef DATAGRAM_SOCKETS if (DATAGRAM_CHAN_P (inchannel)) { ------------------------------------------------------------ revno: 113823 committer: Eli Zaretskii branch nick: trunk timestamp: Mon 2013-08-12 22:48:04 +0300 message: Fix zlib support on MS-Windows. configure.ac (HAVE_ZLIB): Don't use -lz on MinGW. src/decompress.c [WINDOWSNT]: New static variable. (Fzlib_decompress_region) [WINDOWSNT]: Call init_zlib_functions if not yet initialized. diff: === modified file 'ChangeLog' --- ChangeLog 2013-08-12 16:05:58 +0000 +++ ChangeLog 2013-08-12 19:48:04 +0000 @@ -1,3 +1,7 @@ +2013-08-12 Eli Zaretskii + + * configure.ac (HAVE_ZLIB): Don't use -lz on MinGW. + 2013-08-12 Paul Eggert Minor zlib configuration tweaks. === modified file 'configure.ac' --- configure.ac 2013-08-12 16:05:58 +0000 +++ configure.ac 2013-08-12 19:48:04 +0000 @@ -2955,6 +2955,10 @@ fi if test "${HAVE_ZLIB}" = "yes"; then AC_DEFINE([HAVE_ZLIB], 1, [Define to 1 if you have the zlib library (-lz).]) + ### mingw32 doesn't use -lz, since it loads the library dynamically. + if test "${opsys}" = "mingw32"; then + LIBZ= + fi fi AC_SUBST(LIBZ) === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-12 17:02:31 +0000 +++ src/ChangeLog 2013-08-12 19:48:04 +0000 @@ -1,3 +1,9 @@ +2013-08-12 Eli Zaretskii + + * decompress.c [WINDOWSNT]: New static variable. + (Fzlib_decompress_region) [WINDOWSNT]: Call init_zlib_functions if + not yet initialized. + 2013-08-12 Lars Magne Ingebrigtsen * decompress.c (Fzlib_decompress_region): Support zlib === modified file 'src/decompress.c' --- src/decompress.c 2013-08-12 17:02:31 +0000 +++ src/decompress.c 2013-08-12 19:48:04 +0000 @@ -38,7 +38,7 @@ /* Macro for loading zlib functions from the library. */ #define LOAD_ZLIB_FN(lib,func) { \ fn_##func = (void *) GetProcAddress (lib, #func); \ - if (!fn_##func) return 0; \ + if (!fn_##func) return false; \ } DEF_ZLIB_FN (int, inflateInit2_, @@ -50,6 +50,8 @@ DEF_ZLIB_FN (int, inflateEnd, (z_streamp strm)); +static bool zlib_initialized; + static bool init_zlib_functions (void) { @@ -58,13 +60,13 @@ if (!library) { message1 ("zlib library not found"); - return 0; + return false; } LOAD_ZLIB_FN (library, inflateInit2_); LOAD_ZLIB_FN (library, inflate); LOAD_ZLIB_FN (library, inflateEnd); - return 1; + return true; } #define fn_inflateInit2(strm, windowBits) \ @@ -139,6 +141,11 @@ if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) error ("This function can be called only in unibyte buffers"); +#ifdef WINDOWSNT + if (!zlib_initialized) + zlib_initialized = init_zlib_functions (); +#endif + /* This is a unibyte buffer, so character positions and bytes are the same. */ istart = XINT (start); ------------------------------------------------------------ revno: 113822 committer: Lars Magne Ingebrigtsen branch nick: trunk timestamp: Mon 2013-08-12 20:36:05 +0200 message: Add a test for decompressing gzipped data diff: === added directory 'test/automated/data/decompress' === added file 'test/automated/data/decompress/foo-gzipped' Binary files test/automated/data/decompress/foo-gzipped 1970-01-01 00:00:00 +0000 and test/automated/data/decompress/foo-gzipped 2013-08-12 18:36:05 +0000 differ === added file 'test/automated/zlib-tests.el' --- test/automated/zlib-tests.el 1970-01-01 00:00:00 +0000 +++ test/automated/zlib-tests.el 2013-08-12 18:36:05 +0000 @@ -0,0 +1,40 @@ +;;; zlib-tests.el --- Test suite for zlib. + +;; Copyright (C) 2013 Free Software Foundation, Inc. + +;; Author: Lars Ingebrigtsen + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'ert) + +(ert-deftest zlib--decompress () + "Test decompressing a gzipped file." + (when (and (fboundp 'zlib-available-p) + (zlib-available-p)) + (should (string= + (with-temp-buffer + (set-buffer-multibyte nil) + (insert-file-contents-literally "data/decompress/foo-gzipped") + (zlib-decompress-region (point-min) (point-max)) + (buffer-string)) + "foo\n")))) + +(provide 'zlib-tests) + +;;; zlib-tests.el ends here. ------------------------------------------------------------ revno: 113821 author: Grégoire Jadi committer: Lars Magne Ingebrigtsen branch nick: trunk timestamp: Mon 2013-08-12 19:25:22 +0200 message: * mail/sendmail.el (sendmail-send-it): Don't kill the error buffer on error This makes debugging easier. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-08-12 15:11:35 +0000 +++ lisp/ChangeLog 2013-08-12 17:25:22 +0000 @@ -1,3 +1,8 @@ +2013-08-12 Grégoire Jadi + + * mail/sendmail.el (sendmail-send-it): Don't kill the error buffer + if sending fails. This makes debugging easier. + 2013-08-12 Juanma Barranquero * xml.el (xml-parse-tag-1): Use looking-at (this reverts change in === modified file 'lisp/mail/sendmail.el' --- lisp/mail/sendmail.el 2013-01-13 19:48:04 +0000 +++ lisp/mail/sendmail.el 2013-08-12 17:25:22 +0000 @@ -1114,6 +1114,7 @@ (let ((errbuf (if mail-interactive (generate-new-buffer " sendmail errors") 0)) + (error nil) (tembuf (generate-new-buffer " sendmail temp")) (multibyte enable-multibyte-characters) (case-fold-search nil) @@ -1278,10 +1279,13 @@ (exit-value (apply 'call-process-region args))) (cond ((or (null exit-value) (eq 0 exit-value))) ((numberp exit-value) + (setq error t) (error "Sending...failed with exit value %d" exit-value)) ((stringp exit-value) + (setq error t) (error "Sending...terminated by signal: %s" exit-value)) (t + (setq error t) (error "SENDMAIL-SEND-IT -- fall through: %S" exit-value)))) (or fcc-was-found (error "No recipients"))) @@ -1290,12 +1294,15 @@ (goto-char (point-min)) (while (re-search-forward "\n\n* *" nil t) (replace-match "; ")) - (if (not (zerop (buffer-size))) - (error "Sending...failed to %s" - (buffer-substring (point-min) (point-max))))))) + (unless (zerop (buffer-size)) + (setq error t) + (error "Sending...failed to %s" + (buffer-substring (point-min) (point-max))))))) (kill-buffer tembuf) - (if (bufferp errbuf) - (kill-buffer errbuf))))) + (if (and (bufferp errbuf) + (not error)) + (kill-buffer errbuf) + (switch-to-buffer-other-window errbuf))))) (autoload 'rmail-output-to-rmail-buffer "rmailout") ------------------------------------------------------------ revno: 113820 committer: Lars Magne Ingebrigtsen branch nick: trunk timestamp: Mon 2013-08-12 19:02:31 +0200 message: Rename `zlib-decompress-gzipped-region' to `zlib-decompress-region'. Also support zlib-format compression. diff: === modified file 'etc/NEWS' --- etc/NEWS 2013-08-12 13:54:45 +0000 +++ etc/NEWS 2013-08-12 17:02:31 +0000 @@ -43,7 +43,8 @@ ** Emacs can be compiled with zlib support. If this library is present (which it normally is on most systems), the function -`zlib-decompress-gzipped-region' becomes available. +`zlib-decompress-region' becomes available, which can decompress gzip- +and zlib-format compressed data. --- ** Emacs for NS (OSX, GNUStep) can be built with ImageMagick support. === modified file 'lisp/url/ChangeLog' --- lisp/url/ChangeLog 2013-08-12 13:54:45 +0000 +++ lisp/url/ChangeLog 2013-08-12 17:02:31 +0000 @@ -3,6 +3,8 @@ * url-http.el (url-handle-content-transfer-encoding): Renamed `zlib-decompress-gzipped-region' and check whether it's available, too. + (url-handle-content-transfer-encoding): Renamed + `zlib-decompress-region' again. 2013-08-11 Lars Magne Ingebrigtsen === modified file 'lisp/url/url-http.el' --- lisp/url/url-http.el 2013-08-12 13:54:45 +0000 +++ lisp/url/url-http.el 2013-08-12 17:02:31 +0000 @@ -860,14 +860,14 @@ (defun url-handle-content-transfer-encoding () (let ((encoding (mail-fetch-field "content-encoding"))) (when (and encoding - (fboundp 'zlib-decompress-gzipped-region) + (fboundp 'zlib-decompress-region) (zlib-available-p) (equal (downcase encoding) "gzip")) (save-restriction (widen) (goto-char (point-min)) (when (search-forward "\n\n") - (zlib-decompress-gzipped-region (point) (point-max))))))) + (zlib-decompress-region (point) (point-max))))))) ;; Miscellaneous (defun url-http-activate-callback () === modified file 'lisp/url/url-vars.el' --- lisp/url/url-vars.el 2013-08-12 13:54:45 +0000 +++ lisp/url/url-vars.el 2013-08-12 17:02:31 +0000 @@ -210,7 +210,8 @@ (defvar url-request-method nil "The method to use for the next request.") -(defvar url-mime-encoding-string (and (fboundp 'zlib-decompress-gzipped-region) +(defvar url-mime-encoding-string (and (fboundp 'zlib-decompress-region) + (zlib-available-p) "gzip") "String to send in the Accept-encoding: field in HTTP requests.") === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-12 16:05:58 +0000 +++ src/ChangeLog 2013-08-12 17:02:31 +0000 @@ -1,3 +1,8 @@ +2013-08-12 Lars Magne Ingebrigtsen + + * decompress.c (Fzlib_decompress_region): Support zlib + decompression, too, and rename. + 2013-08-12 Paul Eggert Minor zlib configuration tweaks. === modified file 'src/decompress.c' --- src/decompress.c 2013-08-12 16:05:58 +0000 +++ src/decompress.c 2013-08-12 17:02:31 +0000 @@ -119,10 +119,10 @@ #endif } -DEFUN ("zlib-decompress-gzipped-region", Fzlib_decompress_gzipped_region, - Szlib_decompress_gzipped_region, +DEFUN ("zlib-decompress-region", Fzlib_decompress_region, + Szlib_decompress_region, 2, 2, 0, - doc: /* Decompress a gzip-compressed region. + doc: /* Decompress a gzip- or zlib-compressed region. Replace the text in the region by the decompressed data. On failure, return nil and leave the data in place. This function can be called only in unibyte buffers. */) @@ -151,8 +151,9 @@ stream.avail_in = 0; stream.next_in = Z_NULL; - /* This magic number apparently means "this is gzip". */ - if (fn_inflateInit2 (&stream, 16 + MAX_WBITS) != Z_OK) + /* The magic number 32 apparently means "autodect both the gzip and + zlib formats" according to zlib.h. */ + if (fn_inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK) return Qnil; unwind_data.start = iend; @@ -210,7 +211,7 @@ syms_of_decompress (void) { DEFSYM (Qzlib_dll, "zlib"); - defsubr (&Szlib_decompress_gzipped_region); + defsubr (&Szlib_decompress_region); defsubr (&Szlib_available_p); } ------------------------------------------------------------ revno: 113819 committer: Paul Eggert branch nick: trunk timestamp: Mon 2013-08-12 09:05:58 -0700 message: Minor zlib configuration tweaks. * configure.ac (HAVE_ZLIB): Don't assume zlib is linked if PNG is. * src/decompress.c (fn_inflateInit2) [!WINDOWSNT]: Don't assume presence of fn_inflateInit2_ zlib internal function. diff: === modified file 'ChangeLog' --- ChangeLog 2013-08-12 13:15:01 +0000 +++ ChangeLog 2013-08-12 16:05:58 +0000 @@ -1,3 +1,8 @@ +2013-08-12 Paul Eggert + + Minor zlib configuration tweaks. + * configure.ac (HAVE_ZLIB): Don't assume zlib is linked if PNG is. + 2013-08-12 Eli Zaretskii * configure.ac (LIBZ): Comment on w32 peculiarities regarding LIBZ. === modified file 'configure.ac' --- configure.ac 2013-08-12 13:15:01 +0000 +++ configure.ac 2013-08-12 16:05:58 +0000 @@ -2946,21 +2946,12 @@ HAVE_ZLIB=no LIBZ= if test "${with_zlib}" != "no"; then - if test "${HAVE_PNG}" = "yes"; then - ### PNG depends on zlib, so if we have PNG, we have zlib. - ### Note: w32 does not link against libpng, but instead loads it - ### dynamically, but it also does the same with zlib. So it is OK - ### not to have -lz in LIBZ on w32. - HAVE_ZLIB=yes - else - ### No PNG, so check zlib ourselves. - OLIBS=$LIBS - AC_SEARCH_LIBS([inflateEnd], [z], [HAVE_ZLIB=yes]) - LIBS=$OLIBS - case $ac_cv_search_inflateEnd in - -*) LIBZ=$ac_cv_search_inflateEnd ;; - esac - fi + OLIBS=$LIBS + AC_SEARCH_LIBS([inflateEnd], [z], [HAVE_ZLIB=yes]) + LIBS=$OLIBS + case $ac_cv_search_inflateEnd in + -*) LIBZ=$ac_cv_search_inflateEnd ;; + esac fi if test "${HAVE_ZLIB}" = "yes"; then AC_DEFINE([HAVE_ZLIB], 1, [Define to 1 if you have the zlib library (-lz).]) === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-12 13:54:45 +0000 +++ src/ChangeLog 2013-08-12 16:05:58 +0000 @@ -1,3 +1,9 @@ +2013-08-12 Paul Eggert + + Minor zlib configuration tweaks. + * decompress.c (fn_inflateInit2) [!WINDOWSNT]: + Don't assume presence of fn_inflateInit2_ zlib internal function. + 2013-08-12 Lars Magne Ingebrigtsen * decompress.c (Fzlib_decompress_gzipped_region): Rename to === modified file 'src/decompress.c' --- src/decompress.c 2013-08-12 13:54:45 +0000 +++ src/decompress.c 2013-08-12 16:05:58 +0000 @@ -67,17 +67,17 @@ return 1; } +#define fn_inflateInit2(strm, windowBits) \ + fn_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + #else /* !WINDOWSNT */ -#define fn_inflateInit2_ inflateInit2_ +#define fn_inflateInit2 inflateInit2 #define fn_inflate inflate #define fn_inflateEnd inflateEnd #endif /* WINDOWSNT */ -#define fn_inflateInit2(strm, windowBits) \ - fn_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) - struct decompress_unwind_data { ------------------------------------------------------------ revno: 113818 committer: Juanma Barranquero branch nick: trunk timestamp: Mon 2013-08-12 17:11:35 +0200 message: lisp/xml.el (xml-parse-tag-1): Use looking-at. (This reverts change in revno:113793, which breaks the test suite). https://lists.gnu.org/archive/html/emacs-devel/2013-08/msg00263.html diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-08-12 13:15:01 +0000 +++ lisp/ChangeLog 2013-08-12 15:11:35 +0000 @@ -1,3 +1,9 @@ +2013-08-12 Juanma Barranquero + + * xml.el (xml-parse-tag-1): Use looking-at (this reverts change in + revno:113793, which breaks the test suite). + https://lists.gnu.org/archive/html/emacs-devel/2013-08/msg00263.html + 2013-08-12 Eli Zaretskii * term/w32-win.el (dynamic-library-alist): Add DLLs for zlib. === modified file 'lisp/xml.el' --- lisp/xml.el 2013-08-11 00:07:48 +0000 +++ lisp/xml.el 2013-08-12 15:11:35 +0000 @@ -538,7 +538,7 @@ (forward-char 1) ;; Now check that we have the right end-tag. (let ((end (concat ""))) - (while (not (looking-at-p end)) + (while (not (looking-at end)) (cond ((eobp) (error "XML: (Not Well-Formed) End of document while reading element `%s'" ------------------------------------------------------------ revno: 113817 committer: Lars Magne Ingebrigtsen branch nick: trunk timestamp: Mon 2013-08-12 15:54:45 +0200 message: Add the zlib prefix to `decompress-gzipped-region' diff: === modified file 'etc/NEWS' --- etc/NEWS 2013-08-11 19:43:36 +0000 +++ etc/NEWS 2013-08-12 13:54:45 +0000 @@ -43,7 +43,7 @@ ** Emacs can be compiled with zlib support. If this library is present (which it normally is on most systems), the function -`decompress-gzipped-region' becomes available. +`zlib-decompress-gzipped-region' becomes available. --- ** Emacs for NS (OSX, GNUStep) can be built with ImageMagick support. === modified file 'lisp/url/ChangeLog' --- lisp/url/ChangeLog 2013-08-11 20:52:50 +0000 +++ lisp/url/ChangeLog 2013-08-12 13:54:45 +0000 @@ -1,3 +1,9 @@ +2013-08-12 Lars Magne Ingebrigtsen + + * url-http.el (url-handle-content-transfer-encoding): Renamed + `zlib-decompress-gzipped-region' and check whether it's available, + too. + 2013-08-11 Lars Magne Ingebrigtsen * url-vars.el (url-mime-encoding-string): If we have built-in gzip === modified file 'lisp/url/url-http.el' --- lisp/url/url-http.el 2013-08-11 20:52:50 +0000 +++ lisp/url/url-http.el 2013-08-12 13:54:45 +0000 @@ -860,13 +860,14 @@ (defun url-handle-content-transfer-encoding () (let ((encoding (mail-fetch-field "content-encoding"))) (when (and encoding - (fboundp 'decompress-gzipped-region) + (fboundp 'zlib-decompress-gzipped-region) + (zlib-available-p) (equal (downcase encoding) "gzip")) (save-restriction (widen) (goto-char (point-min)) (when (search-forward "\n\n") - (decompress-gzipped-region (point) (point-max))))))) + (zlib-decompress-gzipped-region (point) (point-max))))))) ;; Miscellaneous (defun url-http-activate-callback () === modified file 'lisp/url/url-vars.el' --- lisp/url/url-vars.el 2013-08-11 20:52:50 +0000 +++ lisp/url/url-vars.el 2013-08-12 13:54:45 +0000 @@ -210,7 +210,7 @@ (defvar url-request-method nil "The method to use for the next request.") -(defvar url-mime-encoding-string (and (fboundp 'decompress-gzipped-region) +(defvar url-mime-encoding-string (and (fboundp 'zlib-decompress-gzipped-region) "gzip") "String to send in the Accept-encoding: field in HTTP requests.") === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-12 13:15:01 +0000 +++ src/ChangeLog 2013-08-12 13:54:45 +0000 @@ -1,3 +1,8 @@ +2013-08-12 Lars Magne Ingebrigtsen + + * decompress.c (Fzlib_decompress_gzipped_region): Rename to + include the zlib prefix. + 2013-08-12 Eli Zaretskii * decompress.c [WINDOWSNT]: Include windows.h and w32.h. === modified file 'src/decompress.c' --- src/decompress.c 2013-08-12 13:15:01 +0000 +++ src/decompress.c 2013-08-12 13:54:45 +0000 @@ -119,8 +119,8 @@ #endif } -DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region, - Sdecompress_gzipped_region, +DEFUN ("zlib-decompress-gzipped-region", Fzlib_decompress_gzipped_region, + Szlib_decompress_gzipped_region, 2, 2, 0, doc: /* Decompress a gzip-compressed region. Replace the text in the region by the decompressed data. @@ -210,7 +210,7 @@ syms_of_decompress (void) { DEFSYM (Qzlib_dll, "zlib"); - defsubr (&Sdecompress_gzipped_region); + defsubr (&Szlib_decompress_gzipped_region); defsubr (&Szlib_available_p); } ------------------------------------------------------------ revno: 113816 committer: Eli Zaretskii branch nick: trunk timestamp: Mon 2013-08-12 16:15:01 +0300 message: Fix build with zlib on MS-Windows. configure.ac (LIBZ): Comment on w32 peculiarities regarding LIBZ. src/decompress.c [WINDOWSNT]: Include windows.h and w32.h. (DEF_ZLIB_FN, LOAD_ZLIB_FN) [WINDOWSNT]: New macros. Use them to define static variables that are pointers to zlib functions to be dynamically loaded. (init_zlib_functions) [WINDOWSNT]: New function. (fn_inflateInit2_, fn_inflate, fn_inflateEnd, fn_inflateInit2): New macros. (Fdecompress_gzipped_region, unwind_decompress): Use the fn_* macros instead of invoking the zlib functions directly. (syms_of_decompress): DEFSYM Qzlib_dll. Staticpro Szlib_available_p. lisp/term/w32-win.el (dynamic-library-alist): Add DLLs for zlib. diff: === modified file 'ChangeLog' --- ChangeLog 2013-08-12 00:52:17 +0000 +++ ChangeLog 2013-08-12 13:15:01 +0000 @@ -1,3 +1,7 @@ +2013-08-12 Eli Zaretskii + + * configure.ac (LIBZ): Comment on w32 peculiarities regarding LIBZ. + 2013-08-12 Paul Eggert Merge from gnulib, incorporating: === modified file 'configure.ac' --- configure.ac 2013-08-12 00:04:15 +0000 +++ configure.ac 2013-08-12 13:15:01 +0000 @@ -2948,6 +2948,9 @@ if test "${with_zlib}" != "no"; then if test "${HAVE_PNG}" = "yes"; then ### PNG depends on zlib, so if we have PNG, we have zlib. + ### Note: w32 does not link against libpng, but instead loads it + ### dynamically, but it also does the same with zlib. So it is OK + ### not to have -lz in LIBZ on w32. HAVE_ZLIB=yes else ### No PNG, so check zlib ourselves. === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-08-12 00:09:11 +0000 +++ lisp/ChangeLog 2013-08-12 13:15:01 +0000 @@ -1,3 +1,7 @@ +2013-08-12 Eli Zaretskii + + * term/w32-win.el (dynamic-library-alist): Add DLLs for zlib. + 2013-08-12 Glenn Morris * format.el (format-annotate-function): === modified file 'lisp/term/w32-win.el' --- lisp/term/w32-win.el 2013-04-16 02:41:37 +0000 +++ lisp/term/w32-win.el 2013-08-12 13:15:01 +0000 @@ -229,7 +229,8 @@ '(glib "libglib-2.0-0.dll") '(gobject "libgobject-2.0-0.dll") '(gnutls "libgnutls-28.dll" "libgnutls-26.dll") - '(libxml2 "libxml2-2.dll" "libxml2.dll"))) + '(libxml2 "libxml2-2.dll" "libxml2.dll") + '(zlib "zlib1.dll" "libz-1.dll"))) ;;; multi-tty support (defvar w32-initialized nil === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-12 09:34:00 +0000 +++ src/ChangeLog 2013-08-12 13:15:01 +0000 @@ -1,3 +1,17 @@ +2013-08-12 Eli Zaretskii + + * decompress.c [WINDOWSNT]: Include windows.h and w32.h. + (DEF_ZLIB_FN, LOAD_ZLIB_FN) [WINDOWSNT]: New macros. Use them to + define static variables that are pointers to zlib functions to be + dynamically loaded. + (init_zlib_functions) [WINDOWSNT]: New function. + (fn_inflateInit2_, fn_inflate, fn_inflateEnd, fn_inflateInit2): + New macros. + (Fdecompress_gzipped_region, unwind_decompress): Use the fn_* + macros instead of invoking the zlib functions directly. + (syms_of_decompress): DEFSYM Qzlib_dll. Staticpro + Szlib_available_p. + 2013-08-12 Dmitry Antipov Avoid looping over all frame windows to freeze and unfreeze. === modified file 'src/decompress.c' --- src/decompress.c 2013-08-11 23:09:26 +0000 +++ src/decompress.c 2013-08-12 13:15:01 +0000 @@ -26,6 +26,58 @@ #include "character.h" #include "buffer.h" +static Lisp_Object Qzlib_dll; + +#ifdef WINDOWSNT +#include +#include "w32.h" + +/* Macro for defining functions that will be loaded from the zlib DLL. */ +#define DEF_ZLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args + +/* Macro for loading zlib functions from the library. */ +#define LOAD_ZLIB_FN(lib,func) { \ + fn_##func = (void *) GetProcAddress (lib, #func); \ + if (!fn_##func) return 0; \ + } + +DEF_ZLIB_FN (int, inflateInit2_, + (z_streamp strm, int windowBits, const char *version, int stream_size)); + +DEF_ZLIB_FN (int, inflate, + (z_streamp strm, int flush)); + +DEF_ZLIB_FN (int, inflateEnd, + (z_streamp strm)); + +static bool +init_zlib_functions (void) +{ + HMODULE library = w32_delayed_load (Qzlib_dll); + + if (!library) + { + message1 ("zlib library not found"); + return 0; + } + + LOAD_ZLIB_FN (library, inflateInit2_); + LOAD_ZLIB_FN (library, inflate); + LOAD_ZLIB_FN (library, inflateEnd); + return 1; +} + +#else /* !WINDOWSNT */ + +#define fn_inflateInit2_ inflateInit2_ +#define fn_inflate inflate +#define fn_inflateEnd inflateEnd + +#endif /* WINDOWSNT */ + +#define fn_inflateInit2(strm, windowBits) \ + fn_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + struct decompress_unwind_data { @@ -37,7 +89,7 @@ unwind_decompress (void *ddata) { struct decompress_unwind_data *data = ddata; - inflateEnd (data->stream); + fn_inflateEnd (data->stream); /* Delete any uncompressed data already inserted and restore point. */ if (data->start) @@ -47,6 +99,26 @@ } } +DEFUN ("zlib-available-p", Fzlib_available_p, Szlib_available_p, 0, 0, 0, + doc: /* Return t if zlib decompression is available in this instance of Emacs. */) + (void) +{ +#ifdef WINDOWSNT + Lisp_Object found = Fassq (Qzlib_dll, Vlibrary_cache); + if (CONSP (found)) + return XCDR (found); + else + { + Lisp_Object status; + status = init_zlib_functions () ? Qt : Qnil; + Vlibrary_cache = Fcons (Fcons (Qzlib_dll, status), Vlibrary_cache); + return status; + } +#else + return Qt; +#endif +} + DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region, Sdecompress_gzipped_region, 2, 2, 0, @@ -80,7 +152,7 @@ stream.next_in = Z_NULL; /* This magic number apparently means "this is gzip". */ - if (inflateInit2 (&stream, 16 + MAX_WBITS) != Z_OK) + if (fn_inflateInit2 (&stream, 16 + MAX_WBITS) != Z_OK) return Qnil; unwind_data.start = iend; @@ -111,7 +183,7 @@ stream.avail_in = avail_in; stream.next_out = GPT_ADDR; stream.avail_out = avail_out; - inflate_status = inflate (&stream, Z_NO_FLUSH); + inflate_status = fn_inflate (&stream, Z_NO_FLUSH); pos_byte += avail_in - stream.avail_in; decompressed = avail_out - stream.avail_out; insert_from_gap (decompressed, decompressed, 0); @@ -137,7 +209,9 @@ void syms_of_decompress (void) { + DEFSYM (Qzlib_dll, "zlib"); defsubr (&Sdecompress_gzipped_region); + defsubr (&Szlib_available_p); } #endif /* HAVE_ZLIB */ ------------------------------------------------------------ revno: 113815 committer: Glenn Morris branch nick: trunk timestamp: Mon 2013-08-12 06:17:43 -0400 message: Auto-commit of generated files. diff: === modified file 'autogen/Makefile.in' --- autogen/Makefile.in 2013-08-10 10:18:08 +0000 +++ autogen/Makefile.in 2013-08-12 10:17:43 +0000 @@ -903,6 +903,7 @@ LIBXTR6 = @LIBXTR6@ LIBXT_OTHER = @LIBXT_OTHER@ LIBX_OTHER = @LIBX_OTHER@ +LIBZ = @LIBZ@ LIB_ACL = @LIB_ACL@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ LIB_EACCESS = @LIB_EACCESS@ @@ -1185,6 +1186,7 @@ docdir = @docdir@ dvidir = @dvidir@ etcdir = @etcdir@ +etcdocdir = @etcdocdir@ exec_prefix = @exec_prefix@ gamedir = @gamedir@ gameuser = @gameuser@ === modified file 'autogen/config.in' --- autogen/config.in 2013-08-05 10:17:40 +0000 +++ autogen/config.in 2013-08-12 10:17:43 +0000 @@ -408,10 +408,6 @@ don't. */ #undef HAVE_DECL__PUTENV -/* Define to 1 if you have the declaration of `__fpending', and to 0 if you - don't. */ -#undef HAVE_DECL___FPENDING - /* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you don't. */ #undef HAVE_DECL___SYS_SIGLIST @@ -1190,6 +1186,9 @@ /* Define to 1 if you want to use the X window system. */ #undef HAVE_X_WINDOWS +/* Define to 1 if you have the zlib library (-lz). */ +#undef HAVE_ZLIB + /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL @@ -1205,9 +1204,6 @@ /* Define to 1 if you have the `__executable_start' function. */ #undef HAVE___EXECUTABLE_START -/* Define to 1 if you have the `__fpending' function. */ -#undef HAVE___FPENDING - /* Define to 1 if you have the `__secure_getenv' function. */ #undef HAVE___SECURE_GETENV === modified file 'autogen/configure' --- autogen/configure 2013-08-10 10:18:08 +0000 +++ autogen/configure 2013-08-12 10:17:43 +0000 @@ -1279,6 +1279,7 @@ gameuser gamedir bitmapdir +etcdocdir archlibdir etcdir x_default_search_path @@ -1315,6 +1316,7 @@ LIBGPM LIBGIF LIBTIFF +LIBZ LIBPNG LIBJPEG LIBXPM @@ -1538,6 +1540,7 @@ with_gsettings with_selinux with_gnutls +with_zlib with_file_notification with_makeinfo with_compress_info @@ -2268,6 +2271,7 @@ --without-gsettings don't compile with GSettings support --without-selinux don't compile with SELinux support --without-gnutls don't use -lgnutls for SSL/TLS support + --without-zlib don't compile with zlib decompression support --with-file-notification=LIB use a file notification library (LIB one of: yes, gfile, inotify, w32, no) @@ -3383,7 +3387,6 @@ as_fn_append ac_func_list " fcntl" as_fn_append ac_func_list " fdopendir" as_fn_append ac_header_list " stdio_ext.h" -as_fn_append ac_func_list " __fpending" as_fn_append ac_func_list " fstatat" as_fn_append ac_func_list " fsync" gl_getopt_required=GNU @@ -4010,7 +4013,7 @@ lisppath='${locallisppath}:${standardlisppath}' etcdir='${datadir}/emacs/${version}/etc' archlibdir='${libexecdir}/emacs/${version}/${configuration}' -docdir='${datadir}/emacs/${version}/etc' +etcdocdir='${datadir}/emacs/${version}/etc' gamedir='${localstatedir}/games/emacs' @@ -4356,6 +4359,14 @@ fi +# Check whether --with-zlib was given. +if test "${with_zlib+set}" = set; then : + withval=$with_zlib; +else + with_zlib=$with_features +fi + + # Check whether --with-file-notification was given. if test "${with_file_notification+set}" = set; then : @@ -10056,7 +10067,7 @@ exec_prefix=${ns_appbindir} libexecdir="\${ns_appbindir}/libexec" archlibdir="\${ns_appbindir}/libexec" - docdir="\${ns_appresdir}/etc" + etcdocdir="\${ns_appresdir}/etc" etcdir="\${ns_appresdir}/etc" infodir="\${ns_appresdir}/info" mandir="\${ns_appresdir}/man" @@ -13626,6 +13637,85 @@ fi +HAVE_ZLIB=no +LIBZ= +if test "${with_zlib}" != "no"; then + if test "${HAVE_PNG}" = "yes"; then + ### PNG depends on zlib, so if we have PNG, we have zlib. + HAVE_ZLIB=yes + else + ### No PNG, so check zlib ourselves. + OLIBS=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inflateEnd" >&5 +$as_echo_n "checking for library containing inflateEnd... " >&6; } +if test "${ac_cv_search_inflateEnd+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inflateEnd (); +int +main () +{ +return inflateEnd (); + ; + return 0; +} +_ACEOF +for ac_lib in '' z; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inflateEnd=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_inflateEnd+set}" = set; then : + break +fi +done +if test "${ac_cv_search_inflateEnd+set}" = set; then : + +else + ac_cv_search_inflateEnd=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inflateEnd" >&5 +$as_echo "$ac_cv_search_inflateEnd" >&6; } +ac_res=$ac_cv_search_inflateEnd +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + HAVE_ZLIB=yes +fi + + LIBS=$OLIBS + case $ac_cv_search_inflateEnd in + -*) LIBZ=$ac_cv_search_inflateEnd ;; + esac + fi +fi +if test "${HAVE_ZLIB}" = "yes"; then + +$as_echo "#define HAVE_ZLIB 1" >>confdefs.h + +fi + + + ### Use -ltiff if available, unless `--with-tiff=no'. ### mingw32 doesn't use -ltiff, since it loads the library dynamically. HAVE_TIFF=no @@ -18525,8 +18615,6 @@ - - GNULIB_FCHMODAT=0; GNULIB_FSTAT=0; GNULIB_FSTATAT=0; @@ -22967,27 +23055,40 @@ - - fp_headers=' -# include -# if HAVE_STDIO_EXT_H -# include -# endif -' - ac_fn_c_check_decl "$LINENO" "__fpending" "ac_cv_have_decl___fpending" "$fp_headers -" -if test "x$ac_cv_have_decl___fpending" = x""yes; then : - ac_have_decl=1 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __fpending" >&5 +$as_echo_n "checking for __fpending... " >&6; } +if test "${gl_cv_func___fpending+set}" = set; then : + $as_echo_n "(cached) " >&6 else - ac_have_decl=0 -fi - -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL___FPENDING $ac_have_decl + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #if HAVE_STDIO_EXT_H + # include + #endif + +int +main () +{ +return ! __fpending (stdin); + ; + return 0; +} _ACEOF - - - if test $ac_cv_func___fpending = no; then +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_func___fpending=yes +else + gl_cv_func___fpending=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_func___fpending" >&5 +$as_echo "$gl_cv_func___fpending" >&6; } + + if test $gl_cv_func___fpending = no; then @@ -28869,6 +28970,7 @@ echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT}" echo " Does Emacs use -lotf? ${HAVE_LIBOTF}" echo " Does Emacs use -lxft? ${HAVE_XFT}" +echo " Does Emacs directly use zlib? ${HAVE_ZLIB}" echo " Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}" echo ------------------------------------------------------------ revno: 113814 committer: Dmitry Antipov branch nick: trunk timestamp: Mon 2013-08-12 13:34:00 +0400 message: Avoid looping over all frame windows to freeze and unfreeze. * window.h (struct window): Drop frozen_window_start_p. (freeze_window_starts): Drop prototype. * frame.h (struct frame): New frozen_window_starts flag. (FRAME_WINDOWS_FROZEN): New macro. * window.c (freeze_window_start, freeze_window_starts): Remove. (select_window, replace_window): Adjust users. * xdisp.c (resize_mini_window): Use FRAME_WINDOWS_FROZEN. (window_frozen_p): New function. (redisplay_window): Use it. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-12 07:12:07 +0000 +++ src/ChangeLog 2013-08-12 09:34:00 +0000 @@ -1,3 +1,17 @@ +2013-08-12 Dmitry Antipov + + Avoid looping over all frame windows to freeze and unfreeze. + * window.h (struct window): Drop frozen_window_start_p. + (freeze_window_starts): Drop prototype. + * frame.h (struct frame): New frozen_window_starts flag. + (FRAME_WINDOWS_FROZEN): New macro. + * window.c (freeze_window_start, freeze_window_starts): + Remove. + (select_window, replace_window): Adjust users. + * xdisp.c (resize_mini_window): Use FRAME_WINDOWS_FROZEN. + (window_frozen_p): New function. + (redisplay_window): Use it. + 2013-08-12 Paul Eggert Fix some fd issues when running subprocesses (Bug#15035). === modified file 'src/frame.h' --- src/frame.h 2013-08-03 03:29:03 +0000 +++ src/frame.h 2013-08-12 09:34:00 +0000 @@ -410,6 +410,10 @@ /* Nonzero means that the pointer is invisible. */ unsigned pointer_invisible :1; + /* Nonzero means that all windows except mini-window and + selected window on this frame have frozen window starts. */ + unsigned frozen_window_starts : 1; + /* Nonzero if we should actually display the scroll bars on this frame. */ enum vertical_scroll_bar_type vertical_scroll_bar_type; @@ -761,6 +765,10 @@ /* Not really implemented. */ #define FRAME_WANTS_MODELINE_P(f) (f)->wants_modeline +/* Nonzero if all windows except selected window and mini window + are frozen on frame F. */ +#define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts + /* Nonzero if a size change has been requested for frame F but not yet really put into effect. This can be true temporarily when an X event comes in at a bad time. */ === modified file 'src/window.c' --- src/window.c 2013-08-11 01:30:20 +0000 +++ src/window.c 2013-08-12 09:34:00 +0000 @@ -69,7 +69,6 @@ static void window_scroll (Lisp_Object, EMACS_INT, bool, int); static void window_scroll_pixel_based (Lisp_Object, int, bool, int); static void window_scroll_line_based (Lisp_Object, int, bool, int); -static int freeze_window_start (struct window *, void *); static Lisp_Object window_list (void); static int add_window_to_list (struct window *, void *); static Lisp_Object next_window (Lisp_Object, Lisp_Object, @@ -499,7 +498,6 @@ CHECK_LIVE_WINDOW (window); w = XWINDOW (window); - w->frozen_window_start_p = 0; /* Make the selected window's buffer current. */ Fset_buffer (w->contents); @@ -2055,7 +2053,6 @@ wset_window_end_vpos (n, make_number (0)); wset_window_end_pos (n, make_number (0)); n->window_end_valid = 0; - n->frozen_window_start_p = 0; } tem = o->next; @@ -6453,38 +6450,6 @@ return cont; } - -/* Freeze or unfreeze the window start of W unless it is a - mini-window or the selected window. FREEZE_P non-null means freeze - the window start. */ - -static int -freeze_window_start (struct window *w, void *freeze_p) -{ - if (MINI_WINDOW_P (w) - || (WINDOWP (selected_window) /* Can be nil in corner cases. */ - && (w == XWINDOW (selected_window) - || (MINI_WINDOW_P (XWINDOW (selected_window)) - && ! NILP (Vminibuf_scroll_window) - && w == XWINDOW (Vminibuf_scroll_window))))) - freeze_p = NULL; - - w->frozen_window_start_p = freeze_p != NULL; - return 1; -} - - -/* Freeze or unfreeze the window starts of all leaf windows on frame - F, except the selected window and a mini-window. FREEZE_P non-zero - means freeze the window start. */ - -void -freeze_window_starts (struct frame *f, bool freeze_p) -{ - foreach_window (f, freeze_window_start, freeze_p ? f : 0); -} - - /*********************************************************************** Initialization ***********************************************************************/ === modified file 'src/window.h' --- src/window.h 2013-08-07 10:32:08 +0000 +++ src/window.h 2013-08-12 09:34:00 +0000 @@ -316,11 +316,6 @@ Currently only used for menu bar windows of frames. */ unsigned pseudo_window_p : 1; - /* 1 means the window start of this window is frozen and may not - be changed during redisplay. If point is not in the window, - accept that. */ - unsigned frozen_window_start_p : 1; - /* Non-zero means fringes are drawn outside display margins. Otherwise draw them between margin areas and text. */ unsigned fringes_outside_margins : 1; @@ -888,7 +883,6 @@ extern void resize_frame_windows (struct frame *, int, bool); extern void restore_window_configuration (Lisp_Object); extern void delete_all_child_windows (Lisp_Object); -extern void freeze_window_starts (struct frame *, bool); extern void grow_mini_window (struct window *, int); extern void shrink_mini_window (struct window *); extern int window_relative_x_coord (struct window *, enum window_part, int); === modified file 'src/xdisp.c' --- src/xdisp.c 2013-08-11 01:30:20 +0000 +++ src/xdisp.c 2013-08-12 09:34:00 +0000 @@ -10460,7 +10460,8 @@ if (height > WINDOW_TOTAL_LINES (w)) { int old_height = WINDOW_TOTAL_LINES (w); - freeze_window_starts (f, 1); + + FRAME_WINDOWS_FROZEN (f) = 1; grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; } @@ -10468,7 +10469,8 @@ && (exact_p || BEGV == ZV)) { int old_height = WINDOW_TOTAL_LINES (w); - freeze_window_starts (f, 0); + + FRAME_WINDOWS_FROZEN (f) = 0; shrink_mini_window (w); window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; } @@ -10479,19 +10481,21 @@ if (height > WINDOW_TOTAL_LINES (w)) { int old_height = WINDOW_TOTAL_LINES (w); - freeze_window_starts (f, 1); + + FRAME_WINDOWS_FROZEN (f) = 1; grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; } else if (height < WINDOW_TOTAL_LINES (w)) { int old_height = WINDOW_TOTAL_LINES (w); - freeze_window_starts (f, 0); + + FRAME_WINDOWS_FROZEN (f) = 0; shrink_mini_window (w); if (height) { - freeze_window_starts (f, 1); + FRAME_WINDOWS_FROZEN (f) = 1; grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); } @@ -10874,6 +10878,31 @@ && (w->column_number_displayed != current_column ())); } +/* Nonzero if window start of W is frozen and may not be changed during + redisplay. */ + +static bool +window_frozen_p (struct window *w) +{ + if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w)))) + { + Lisp_Object window; + + XSETWINDOW (window, w); + if (MINI_WINDOW_P (w)) + return 0; + else if (EQ (window, selected_window)) + return 0; + else if (MINI_WINDOW_P (XWINDOW (selected_window)) + && EQ (window, Vminibuf_scroll_window)) + /* This special window can't be frozen too. */ + return 0; + else + return 1; + } + return 0; +} + /*********************************************************************** Mode Lines and Frame Titles ***********************************************************************/ @@ -15510,7 +15539,7 @@ /* Handle case where place to start displaying has been specified, unless the specified location is outside the accessible range. */ - if (w->force_start || w->frozen_window_start_p) + if (w->force_start || window_frozen_p (w)) { /* We set this later on if we have to adjust point. */ int new_vpos = -1; @@ -15555,7 +15584,7 @@ goto need_larger_matrices; } - if (w->cursor.vpos < 0 && !w->frozen_window_start_p) + if (w->cursor.vpos < 0 && !window_frozen_p (w)) { /* If point does not appear, try to move point so it does appear. The desired matrix has been built above, so we ------------------------------------------------------------ revno: 113813 fixes bug: http://debbugs.gnu.org/15035 committer: Paul Eggert branch nick: trunk timestamp: Mon 2013-08-12 00:12:07 -0700 message: Fix some fd issues when running subprocesses. Fix bugs that can leak files or file descriptors on errors. Don't unlink open temp files, as that's hard for users to diagnose when things go awry (e.g., temp disk exhausted). Don't bother to lock temp files. Check for invalid recursion. * callproc.c (synch_process_fd): Remove. All uses removed. (synch_process_tempfile): New var or macro. (CALLPROC_STDOUT, CALLPROC_STDERR, CALLPROC_PIPEREAD, CALLPROC_FDS): New constants. (record_kill_process): New arg, the temp name. All callers changed. (delete_temp_file): Now just a simple wrapper around unlink. (call_process_kill): New arg, the call_process_fd array. Close them all. Clear synch_process_pid. Remove the temp file, or arrange for it to be removed. (call_process_cleanup) [MSDOS]: Arg no longer contains file name; that's been moved to synch_process_tempfile. Caller changed. Do not remove the tempfile; that's now call_process_kill's responsibility. (call_process_cleanup) [!MSDOS]: Do not record unwind-protect for call_process_kill; the caller now does that. (call_process_cleanup): Do not close the process fd; that's now call_process_kill's responsibility. (Fcall_process): Implement via new function call_process, which has most of the old body of Fcall_process, but with a different API. (call_process): New function that does not open or close filefd if it is nonnegative. Record which fds need to be closed, and let call_process_kill close (and remove the tempfile, on MSDOS) on error. Signal an error if invoked recursively (could be done via a hook). Simplify creation of the tempfile in the MSDOS case. Don't create the output file until after checking for the executable. Report any failure to open /dev/null. Don't open /dev/null for writing twice; once is enough. Don't create pipe if all output is being discarded or sent to file. Don't worry about setting up the coding system or reading from the pipe if all output is being discarded. Hoist fd_error local into top level, to lessen block nesting. Don't record deleted pid here; now done by Fcall_process_region. (Fcall_process) [MSDOS]: Report mktemp failure immediately, and note its success in synch_process_tempfile. Do not leak resources when child_setup fails. (Fcall_process) [!MSDOS && !WINDOWSNT]: Remove duplicate assignment to child_errno. Remove unnecessary close of fd0; it's close-on-exec. (create_temp_file): Now returns open fd, with an additional Lisp_Object * argument to return the name. All callers changed. Do not close the file; rewind it instead, and leave it open for the caller. Do not lock the temp file. Unwind-protect the file and the file-descriptor. (Fcall_process_region): If the input is /dev/null, unwind-protect it. If an asynchrounous process, record it here, not in call_process. (syms_of_callproc) [MSDOS]: Initialize synch_process_tempfile. * eval.c (set_unwind_protect): New function. * fileio.c (write_region): New function, generalized from the old Fwrite_region. Do not lock temp files. (Fwrite_region): Use it. * lisp.h (set_unwind_protect, write_region): New decls. * process.c: Include . (make_process): Mark fds as initially closed. (deleted_pid_list): Now a list of pid-filename pairs. All uses changed. (close_process_fd): New function. (SUBPROCESS_STDIN, WRITE_TO_SUBPROCESS, READ_FROM_SUBPROCESS) (SUBPROCESS_STDOUT, READ_FROM_EXEC_MONITOR, EXEC_MONITOR_OUTPUT): New constants. Verify that their number matches PROCESS_OPEN_FDS. (create_process, create_pty, Fmake_serial_process) (server_accept_connection): Record which fds need to be closed, and let deactivate_process close them. (Fmake_network_process): Do not discard the unwind-protect until it's safe to do so. (deactivate_process): Close the fds opened by create_process etc. (Fprocess_send_eof): Adjust to new way of recording open fds. Report an error if /dev/null can't be opened, instead of aborting. * process.h (PROCESS_OPEN_FDS): New constant. (struct Lisp_Process): New member open_fds. (record_kill_process, record_deleted_pid): Adjust signatures. (record_deleted_pid): Move decl here ... * syswait.h (record_deleted_pid): ... from here. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-08-11 23:09:26 +0000 +++ src/ChangeLog 2013-08-12 07:12:07 +0000 @@ -1,3 +1,82 @@ +2013-08-12 Paul Eggert + + Fix some fd issues when running subprocesses (Bug#15035). + Fix bugs that can leak files or file descriptors on errors. + Don't unlink open temp files, as that's hard for users to diagnose + when things go awry (e.g., temp disk exhausted). + Don't bother to lock temp files. Check for invalid recursion. + * callproc.c (synch_process_fd): Remove. All uses removed. + (synch_process_tempfile): New var or macro. + (CALLPROC_STDOUT, CALLPROC_STDERR, CALLPROC_PIPEREAD, CALLPROC_FDS): + New constants. + (record_kill_process): New arg, the temp name. All callers changed. + (delete_temp_file): Now just a simple wrapper around unlink. + (call_process_kill): New arg, the call_process_fd array. + Close them all. Clear synch_process_pid. Remove the temp file, + or arrange for it to be removed. + (call_process_cleanup) [MSDOS]: Arg no longer contains file name; + that's been moved to synch_process_tempfile. Caller changed. + Do not remove the tempfile; that's now call_process_kill's + responsibility. + (call_process_cleanup) [!MSDOS]: Do not record unwind-protect for + call_process_kill; the caller now does that. + (call_process_cleanup): Do not close the process fd; that's now + call_process_kill's responsibility. + (Fcall_process): Implement via new function call_process, which + has most of the old body of Fcall_process, but with a different API. + (call_process): New function that does not open or close filefd if + it is nonnegative. Record which fds need to be closed, and let + call_process_kill close (and remove the tempfile, on MSDOS) on error. + Signal an error if invoked recursively (could be done via a hook). + Simplify creation of the tempfile in the MSDOS case. + Don't create the output file until after checking for the executable. + Report any failure to open /dev/null. + Don't open /dev/null for writing twice; once is enough. + Don't create pipe if all output is being discarded or sent to file. + Don't worry about setting up the coding system or reading from the + pipe if all output is being discarded. + Hoist fd_error local into top level, to lessen block nesting. + Don't record deleted pid here; now done by Fcall_process_region. + (Fcall_process) [MSDOS]: Report mktemp failure immediately, + and note its success in synch_process_tempfile. + Do not leak resources when child_setup fails. + (Fcall_process) [!MSDOS && !WINDOWSNT]: Remove duplicate assignment + to child_errno. Remove unnecessary close of fd0; it's close-on-exec. + (create_temp_file): Now returns open fd, with an additional + Lisp_Object * argument to return the name. All callers changed. + Do not close the file; rewind it instead, and leave it open for + the caller. Do not lock the temp file. Unwind-protect the file + and the file-descriptor. + (Fcall_process_region): If the input is /dev/null, unwind-protect it. + If an asynchrounous process, record it here, not in call_process. + (syms_of_callproc) [MSDOS]: Initialize synch_process_tempfile. + * eval.c (set_unwind_protect): New function. + * fileio.c (write_region): New function, generalized from the + old Fwrite_region. Do not lock temp files. + (Fwrite_region): Use it. + * lisp.h (set_unwind_protect, write_region): New decls. + * process.c: Include . + (make_process): Mark fds as initially closed. + (deleted_pid_list): Now a list of pid-filename pairs. + All uses changed. + (close_process_fd): New function. + (SUBPROCESS_STDIN, WRITE_TO_SUBPROCESS, READ_FROM_SUBPROCESS) + (SUBPROCESS_STDOUT, READ_FROM_EXEC_MONITOR, EXEC_MONITOR_OUTPUT): + New constants. Verify that their number matches PROCESS_OPEN_FDS. + (create_process, create_pty, Fmake_serial_process) + (server_accept_connection): Record which fds need to be closed, + and let deactivate_process close them. + (Fmake_network_process): Do not discard the unwind-protect + until it's safe to do so. + (deactivate_process): Close the fds opened by create_process etc. + (Fprocess_send_eof): Adjust to new way of recording open fds. + Report an error if /dev/null can't be opened, instead of aborting. + * process.h (PROCESS_OPEN_FDS): New constant. + (struct Lisp_Process): New member open_fds. + (record_kill_process, record_deleted_pid): Adjust signatures. + (record_deleted_pid): Move decl here ... + * syswait.h (record_deleted_pid): ... from here. + 2013-08-11 Paul Eggert * decompress.c: Fix bugs with large buffers and weird inputs. === modified file 'src/callproc.c' --- src/callproc.c 2013-08-04 16:56:56 +0000 +++ src/callproc.c 2013-08-12 07:12:07 +0000 @@ -68,9 +68,10 @@ /* Pattern used by call-process-region to make temp files. */ static Lisp_Object Vtemp_file_name_pattern; -/* The next two variables are valid only while record-unwind-protect - is in place during call-process for a synchronous subprocess. At - other times, their contents are irrelevant. Doing this via static +/* The next two variables are used while record-unwind-protect is in place + during call-process for a subprocess for which record_deleted_pid has + not yet been called. At other times, synch_process_pid is zero and + synch_process_tempfile's contents are irrelevant. Doing this via static C variables is more convenient than putting them into the arguments of record-unwind-protect, as they need to be updated at randomish times in the code, and Lisp cannot always store these values as @@ -80,8 +81,28 @@ /* If nonzero, a process-ID that has not been reaped. */ static pid_t synch_process_pid; -/* If nonnegative, a file descriptor that has not been closed. */ -static int synch_process_fd; +/* If a string, the name of a temp file that has not been removed. */ +#ifdef MSDOS +static Lisp_Object synch_process_tempfile; +#else +# define synch_process_tempfile make_number (0) +#endif + +/* Indexes of file descriptors that need closing on call_process_kill. */ +enum + { + /* The subsidiary process's stdout and stderr. stdin is handled + separately, in either Fcall_process_region or create_temp_file. */ + CALLPROC_STDOUT, CALLPROC_STDERR, + + /* How to read from a pipe (or substitute) from the subsidiary process. */ + CALLPROC_PIPEREAD, + + /* A bound on the number of file descriptors. */ + CALLPROC_FDS + }; + +static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int); /* Block SIGCHLD. */ @@ -107,80 +128,68 @@ reaped on receipt of the first SIGCHLD after the critical section. */ void -record_kill_process (struct Lisp_Process *p) +record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) { block_child_signal (); if (p->alive) { + record_deleted_pid (p->pid, tempfile); p->alive = 0; - record_deleted_pid (p->pid); kill (- p->pid, SIGKILL); } unblock_child_signal (); } -/* Clean up when exiting call_process_cleanup. */ - -static void -call_process_kill (void) -{ - if (synch_process_fd >= 0) - emacs_close (synch_process_fd); +/* Clean up files, file descriptors and processes created by Fcall_process. */ + +static void +delete_temp_file (Lisp_Object name) +{ + unlink (SSDATA (name)); +} + +static void +call_process_kill (void *ptr) +{ + int *callproc_fd = ptr; + int i; + for (i = 0; i < CALLPROC_FDS; i++) + if (0 <= callproc_fd[i]) + emacs_close (callproc_fd[i]); if (synch_process_pid) { struct Lisp_Process proc; proc.alive = 1; proc.pid = synch_process_pid; - record_kill_process (&proc); + record_kill_process (&proc, synch_process_tempfile); + synch_process_pid = 0; } + else if (STRINGP (synch_process_tempfile)) + delete_temp_file (synch_process_tempfile); } -/* Clean up when exiting Fcall_process. - On MSDOS, delete the temporary file on any kind of termination. - On Unix, kill the process and any children on termination by signal. */ +/* Clean up when exiting Fcall_process: restore the buffer, and + kill the subsidiary process group if the process still exists. */ static void -call_process_cleanup (Lisp_Object arg) +call_process_cleanup (Lisp_Object buffer) { -#ifdef MSDOS - Lisp_Object buffer = Fcar (arg); - Lisp_Object file = Fcdr (arg); -#else - Lisp_Object buffer = arg; -#endif - Fset_buffer (buffer); -#ifndef MSDOS - /* If the process still exists, kill its process group. */ if (synch_process_pid) { - ptrdiff_t count = SPECPDL_INDEX (); kill (-synch_process_pid, SIGINT); - record_unwind_protect_void (call_process_kill); message1 ("Waiting for process to die...(type C-g again to kill it instantly)"); immediate_quit = 1; QUIT; wait_for_termination (synch_process_pid, 0, 1); synch_process_pid = 0; immediate_quit = 0; - specpdl_ptr = specpdl + count; /* Discard the unwind protect. */ message1 ("Waiting for process to die...done"); } -#endif - - if (synch_process_fd >= 0) - emacs_close (synch_process_fd); - -#ifdef MSDOS - /* FILE is "" when we didn't actually create a temporary file in - call-process. */ - if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0')) - unlink (SDATA (file)); -#endif } #ifdef DOS_NT @@ -218,10 +227,42 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object infile, buffer, current_dir, path; + Lisp_Object infile, encoded_infile; + int filefd; + struct gcpro gcpro1; + ptrdiff_t count = SPECPDL_INDEX (); + + if (nargs >= 2 && ! NILP (args[1])) + { + infile = Fexpand_file_name (args[1], BVAR (current_buffer, directory)); + CHECK_STRING (infile); + } + else + infile = build_string (NULL_DEVICE); + + GCPRO1 (infile); + encoded_infile = STRING_MULTIBYTE (infile) ? ENCODE_FILE (infile) : infile; + + filefd = emacs_open (SSDATA (encoded_infile), O_RDONLY, 0); + if (filefd < 0) + report_file_error ("Opening process input file", infile); + record_unwind_protect_int (close_file_unwind, filefd); + UNGCPRO; + return unbind_to (count, call_process (nargs, args, filefd)); +} + +/* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. + At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ + +static Lisp_Object +call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) +{ + Lisp_Object buffer, current_dir, path; bool display_p; - int fd0, fd1, filefd; + int fd0; + int callproc_fd[CALLPROC_FDS]; int status; + ptrdiff_t i; ptrdiff_t count = SPECPDL_INDEX (); USE_SAFE_ALLOCA; @@ -231,19 +272,21 @@ Lisp_Object error_file; Lisp_Object output_file = Qnil; #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ - char *outf, *tempfile = NULL; - int outfilefd; + char *tempfile = NULL; int pid; #else pid_t pid; #endif int child_errno; - int fd_output = -1; + int fd_output, fd_error; struct coding_system process_coding; /* coding-system of process output */ struct coding_system argument_coding; /* coding-system of arguments */ /* Set to the return value of Ffind_operation_coding_system. */ Lisp_Object coding_systems; - bool output_to_buffer = 1; + bool discard_output; + + if (synch_process_pid) + error ("call-process invoked recursively"); /* Qt denotes that Ffind_operation_coding_system is not yet called. */ coding_systems = Qt; @@ -262,7 +305,6 @@ /* Decide the coding-system for giving arguments. */ { Lisp_Object val, *args2; - ptrdiff_t i; /* If arguments are supplied, we may have to encode them. */ if (nargs >= 5) @@ -301,24 +343,16 @@ } } - if (nargs >= 2 && ! NILP (args[1])) - { - infile = Fexpand_file_name (args[1], BVAR (current_buffer, directory)); - CHECK_STRING (infile); - } + if (nargs < 3) + buffer = Qnil; else - infile = build_string (NULL_DEVICE); - - if (nargs >= 3) { buffer = args[2]; /* If BUFFER is a list, its meaning is (BUFFER-FOR-STDOUT FILE-FOR-STDERR), unless the first element is :file, in which case see the next paragraph. */ - if (CONSP (buffer) - && (! SYMBOLP (XCAR (buffer)) - || strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file"))) + if (CONSP (buffer) && !EQ (XCAR (buffer), QCfile)) { if (CONSP (XCDR (buffer))) { @@ -335,9 +369,7 @@ } /* If the buffer is (still) a list, it might be a (:file "file") spec. */ - if (CONSP (buffer) - && SYMBOLP (XCAR (buffer)) - && ! strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file")) + if (CONSP (buffer) && EQ (XCAR (buffer), QCfile)) { output_file = Fexpand_file_name (XCAR (XCDR (buffer)), BVAR (current_buffer, directory)); @@ -345,9 +377,7 @@ buffer = Qnil; } - if (!(EQ (buffer, Qnil) - || EQ (buffer, Qt) - || INTEGERP (buffer))) + if (! (NILP (buffer) || EQ (buffer, Qt) || INTEGERP (buffer))) { Lisp_Object spec_buffer; spec_buffer = buffer; @@ -358,8 +388,6 @@ CHECK_BUFFER (buffer); } } - else - buffer = Qnil; /* Make sure that the child will be able to chdir to the current buffer's current directory, or its unhandled equivalent. We @@ -372,11 +400,11 @@ protected by the caller, so all we really have to worry about is buffer. */ { - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; current_dir = BVAR (current_buffer, directory); - GCPRO5 (infile, buffer, current_dir, error_file, output_file); + GCPRO4 (buffer, current_dir, error_file, output_file); current_dir = Funhandled_file_name_directory (current_dir); if (NILP (current_dir)) @@ -390,8 +418,6 @@ report_file_error ("Setting current directory", BVAR (current_buffer, directory)); - if (STRING_MULTIBYTE (infile)) - infile = ENCODE_FILE (infile); if (STRING_MULTIBYTE (current_dir)) current_dir = ENCODE_FILE (current_dir); if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) @@ -403,44 +429,23 @@ display_p = INTERACTIVE && nargs >= 4 && !NILP (args[3]); - filefd = emacs_open (SSDATA (infile), O_RDONLY, 0); - if (filefd < 0) - { - int open_errno = errno; - report_file_errno ("Opening process input file", DECODE_FILE (infile), - open_errno); - } - - if (STRINGP (output_file)) - { - fd_output = emacs_open (SSDATA (output_file), - O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, - default_output_mode); - if (fd_output < 0) - { - int open_errno = errno; - output_file = DECODE_FILE (output_file); - report_file_errno ("Opening process output file", - output_file, open_errno); - } - if (STRINGP (error_file) || NILP (error_file)) - output_to_buffer = 0; - } + for (i = 0; i < CALLPROC_FDS; i++) + callproc_fd[i] = -1; +#ifdef MSDOS + synch_process_tempfile = make_number (0); +#endif + record_unwind_protect_ptr (call_process_kill, callproc_fd); /* Search for program; barf if not found. */ { - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + struct gcpro gcpro1, gcpro2, gcpro3; int ok; - GCPRO4 (infile, buffer, current_dir, error_file); + GCPRO3 (buffer, current_dir, error_file); ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK)); UNGCPRO; if (ok < 0) - { - int openp_errno = errno; - emacs_close (filefd); - report_file_errno ("Searching for program", args[0], openp_errno); - } + report_file_error ("Searching for program", args[0]); } /* If program file name starts with /: for quoting a magic name, @@ -452,9 +457,9 @@ new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); { - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; - GCPRO5 (infile, buffer, current_dir, path, error_file); + GCPRO4 (buffer, current_dir, path, error_file); if (nargs > 4) { ptrdiff_t i; @@ -479,254 +484,213 @@ UNGCPRO; } -#ifdef MSDOS /* MW, July 1993 */ + discard_output = INTEGERP (buffer) || (NILP (buffer) && NILP (output_file)); - /* If we're redirecting STDOUT to a file, that file is already open - on fd_output. */ - if (fd_output < 0) +#ifdef MSDOS + if (! discard_output && ! STRINGP (output_file)) { - if ((outf = egetenv ("TMPDIR"))) - strcpy (tempfile = alloca (strlen (outf) + 20), outf); - else - { - tempfile = alloca (20); - *tempfile = '\0'; - } + char const *tmpdir = egetenv ("TMPDIR"); + char const *outf = tmpdir ? tmpdir : ""; + tempfile = alloca (strlen (outf) + 20); + strcpy (tempfile, outf); dostounix_filename (tempfile, 0); if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') strcat (tempfile, "/"); strcat (tempfile, "detmp.XXX"); mktemp (tempfile); - outfilefd = emacs_open (tempfile, O_WRONLY | O_CREAT | O_TRUNC, - S_IREAD | S_IWRITE); - if (outfilefd < 0) + if (!*tempfile) + report_file_error ("Opening process output file", Qnil); + output_file = build_string (tempfile); + synch_process_tempfile = output_file; + } +#endif + + if (discard_output) + { + fd_output = emacs_open (NULL_DEVICE, O_WRONLY, 0); + if (fd_output < 0) + report_file_error ("Opening null device", Qnil); + } + else if (STRINGP (output_file)) + { + fd_output = emacs_open (SSDATA (output_file), + O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, + default_output_mode); + if (fd_output < 0) { int open_errno = errno; - emacs_close (filefd); + output_file = DECODE_FILE (output_file); report_file_errno ("Opening process output file", - build_string (tempfile), open_errno); + output_file, open_errno); } } else - outfilefd = fd_output; - fd0 = filefd; - fd1 = outfilefd; -#endif /* MSDOS */ - - if (INTEGERP (buffer)) - { - fd0 = -1; - fd1 = emacs_open (NULL_DEVICE, O_WRONLY, 0); - } - else - { -#ifndef MSDOS + { int fd[2]; if (emacs_pipe (fd) != 0) - { - int pipe_errno = errno; - emacs_close (filefd); - report_file_errno ("Creating process pipe", Qnil, pipe_errno); - } - fd0 = fd[0]; - fd1 = fd[1]; -#endif + report_file_error ("Creating process pipe", Qnil); + callproc_fd[CALLPROC_PIPEREAD] = fd[0]; + fd_output = fd[1]; } - - { - int fd_error = fd1; - - if (fd_output >= 0) - fd1 = fd_output; - - if (NILP (error_file)) - fd_error = emacs_open (NULL_DEVICE, O_WRONLY, 0); - else if (STRINGP (error_file)) - fd_error = emacs_open (SSDATA (error_file), + callproc_fd[CALLPROC_STDOUT] = fd_output; + + fd_error = fd_output; + + if (STRINGP (error_file) || (NILP (error_file) && !discard_output)) + { + fd_error = emacs_open ((STRINGP (error_file) + ? SSDATA (error_file) + : NULL_DEVICE), O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, default_output_mode); - - if (fd_error < 0) - { - int open_errno = errno; - emacs_close (filefd); - if (fd0 != filefd) - emacs_close (fd0); - if (fd1 >= 0) - emacs_close (fd1); -#ifdef MSDOS - unlink (tempfile); -#endif - if (NILP (error_file)) - error_file = build_string (NULL_DEVICE); - else if (STRINGP (error_file)) - error_file = DECODE_FILE (error_file); - report_file_errno ("Cannot redirect stderr", error_file, open_errno); - } + if (fd_error < 0) + { + int open_errno = errno; + report_file_errno ("Cannot redirect stderr", + (STRINGP (error_file) + ? DECODE_FILE (error_file) + : build_string (NULL_DEVICE)), + open_errno); + } + callproc_fd[CALLPROC_STDERR] = fd_error; + } #ifdef MSDOS /* MW, July 1993 */ - /* Note that on MSDOS `child_setup' actually returns the child process - exit status, not its PID, so assign it to status below. */ - pid = child_setup (filefd, outfilefd, fd_error, new_argv, 0, current_dir); - child_errno = errno; - - emacs_close (outfilefd); - if (fd_error != outfilefd) - emacs_close (fd_error); - if (pid < 0) - { - synchronize_system_messages_locale (); - return - code_convert_string_norecord (build_string (strerror (child_errno)), - Vlocale_coding_system, 0); - } - status = pid; - fd1 = -1; /* No harm in closing that one! */ - if (tempfile) - { - /* Since CRLF is converted to LF within `decode_coding', we - can always open a file with binary mode. */ - fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); - if (fd0 < 0) - { - int open_errno = errno; - unlink (tempfile); - emacs_close (filefd); - report_file_errno ("Cannot re-open temporary file", - build_string (tempfile), open_errno); - } - } - else - fd0 = -1; /* We are not going to read from tempfile. */ -#endif /* MSDOS */ - - /* Do the unwind-protect now, even though the pid is not known, so - that no storage allocation is done in the critical section. - The actual PID will be filled in during the critical section. */ - synch_process_pid = 0; - synch_process_fd = fd0; - -#ifdef MSDOS - /* MSDOS needs different cleanup information. */ - record_unwind_protect (call_process_cleanup, - Fcons (Fcurrent_buffer (), - build_string (tempfile ? tempfile : ""))); -#else - record_unwind_protect (call_process_cleanup, Fcurrent_buffer ()); - - block_input (); - block_child_signal (); - -#ifdef WINDOWSNT - pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); - /* We need to record the input file of this child, for when we are - called from call-process-region to create an async subprocess. - That's because call-process-region's unwind procedure will - attempt to delete the temporary input file, which will fail - because that file is still in use. Recording it with the child - will allow us to delete the file when the subprocess exits. - The second part of this is in delete_temp_file, q.v. */ - if (pid > 0 && INTEGERP (buffer) && nargs >= 2 && !NILP (args[1])) - record_infile (pid, xstrdup (SSDATA (infile))); -#else /* not WINDOWSNT */ - - /* vfork, and prevent local vars from being clobbered by the vfork. */ + /* Note that on MSDOS `child_setup' actually returns the child process + exit status, not its PID, so assign it to status below. */ + pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); + + if (pid < 0) { - Lisp_Object volatile buffer_volatile = buffer; - Lisp_Object volatile coding_systems_volatile = coding_systems; - Lisp_Object volatile current_dir_volatile = current_dir; - bool volatile display_p_volatile = display_p; - bool volatile output_to_buffer_volatile = output_to_buffer; - bool volatile sa_must_free_volatile = sa_must_free; - int volatile fd1_volatile = fd1; - int volatile fd_error_volatile = fd_error; - int volatile fd_output_volatile = fd_output; - int volatile filefd_volatile = filefd; - ptrdiff_t volatile count_volatile = count; - ptrdiff_t volatile sa_count_volatile = sa_count; - char **volatile new_argv_volatile = new_argv; - - pid = vfork (); child_errno = errno; - - buffer = buffer_volatile; - coding_systems = coding_systems_volatile; - current_dir = current_dir_volatile; - display_p = display_p_volatile; - output_to_buffer = output_to_buffer_volatile; - sa_must_free = sa_must_free_volatile; - fd1 = fd1_volatile; - fd_error = fd_error_volatile; - fd_output = fd_output_volatile; - filefd = filefd_volatile; - count = count_volatile; - sa_count = sa_count_volatile; - new_argv = new_argv_volatile; - - fd0 = synch_process_fd; + unbind_to (count, Qnil); + synchronize_system_messages_locale (); + return + code_convert_string_norecord (build_string (strerror (child_errno)), + Vlocale_coding_system, 0); } + status = pid; - if (pid == 0) + for (i = 0; i < CALLPROC_FDS; i++) + if (0 <= callproc_fd[i]) { - unblock_child_signal (); - - if (fd0 >= 0) - emacs_close (fd0); - - setsid (); - - /* Emacs ignores SIGPIPE, but the child should not. */ - signal (SIGPIPE, SIG_DFL); - - child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); + emacs_close (callproc_fd[i]); + callproc_fd[i] = -1; } + emacs_close (filefd); + clear_unwind_protect (count - 1); + + if (tempfile) + { + /* Since CRLF is converted to LF within `decode_coding', we + can always open a file with binary mode. */ + callproc_fd[CALLPROC_PIPEREAD] = emacs_open (tempfile, + O_RDONLY | O_BINARY, 0); + if (callproc_fd[CALLPROC_PIPEREAD] < 0) + { + int open_errno = errno; + report_file_errno ("Cannot re-open temporary file", + build_string (tempfile), open_errno); + } + } + +#endif /* MSDOS */ + + /* Do the unwind-protect now, even though the pid is not known, so + that no storage allocation is done in the critical section. + The actual PID will be filled in during the critical section. */ + record_unwind_protect (call_process_cleanup, Fcurrent_buffer ()); + +#ifndef MSDOS + + block_input (); + block_child_signal (); + +#ifdef WINDOWSNT + pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); +#else /* not WINDOWSNT */ + + /* vfork, and prevent local vars from being clobbered by the vfork. */ + { + Lisp_Object volatile buffer_volatile = buffer; + Lisp_Object volatile coding_systems_volatile = coding_systems; + Lisp_Object volatile current_dir_volatile = current_dir; + bool volatile display_p_volatile = display_p; + bool volatile sa_must_free_volatile = sa_must_free; + int volatile fd_error_volatile = fd_error; + int volatile filefd_volatile = filefd; + ptrdiff_t volatile count_volatile = count; + ptrdiff_t volatile sa_count_volatile = sa_count; + char **volatile new_argv_volatile = new_argv; + int volatile callproc_fd_volatile[CALLPROC_FDS]; + for (i = 0; i < CALLPROC_FDS; i++) + callproc_fd_volatile[i] = callproc_fd[i]; + + pid = vfork (); + + buffer = buffer_volatile; + coding_systems = coding_systems_volatile; + current_dir = current_dir_volatile; + display_p = display_p_volatile; + sa_must_free = sa_must_free_volatile; + fd_error = fd_error_volatile; + filefd = filefd_volatile; + count = count_volatile; + sa_count = sa_count_volatile; + new_argv = new_argv_volatile; + + for (i = 0; i < CALLPROC_FDS; i++) + callproc_fd[i] = callproc_fd_volatile[i]; + fd_output = callproc_fd[CALLPROC_STDOUT]; + } + + if (pid == 0) + { + unblock_child_signal (); + + setsid (); + + /* Emacs ignores SIGPIPE, but the child should not. */ + signal (SIGPIPE, SIG_DFL); + + child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); + } #endif /* not WINDOWSNT */ - child_errno = errno; - - if (pid > 0) - { - if (INTEGERP (buffer)) - record_deleted_pid (pid); - else - synch_process_pid = pid; - } - - unblock_child_signal (); - unblock_input (); - - /* The MSDOS case did this already. */ - if (fd_error >= 0) - emacs_close (fd_error); + child_errno = errno; + + if (pid > 0) + synch_process_pid = pid; + + unblock_child_signal (); + unblock_input (); + #endif /* not MSDOS */ - /* Close most of our file descriptors, but not fd0 - since we will use that to read input from. */ - emacs_close (filefd); - if (fd_output >= 0) - emacs_close (fd_output); - if (fd1 >= 0 && fd1 != fd_error) - emacs_close (fd1); - } - if (pid < 0) report_file_errno ("Doing vfork", Qnil, child_errno); + /* Close our file descriptors, except for callproc_fd[CALLPROC_PIPEREAD] + since we will use that to read input from. */ + for (i = 0; i < CALLPROC_FDS; i++) + if (i != CALLPROC_PIPEREAD && 0 <= callproc_fd[i]) + { + emacs_close (callproc_fd[i]); + callproc_fd[i] = -1; + } + emacs_close (filefd); + clear_unwind_protect (count - 1); + if (INTEGERP (buffer)) return unbind_to (count, Qnil); if (BUFFERP (buffer)) Fset_buffer (buffer); - if (NILP (buffer)) - { - /* If BUFFER is nil, we must read process output once and then - discard it, so setup coding system but with nil. */ - setup_coding_system (Qnil, &process_coding); - process_coding.dst_multibyte = 0; - } - else + fd0 = callproc_fd[CALLPROC_PIPEREAD]; + + if (0 <= fd0) { Lisp_Object val, *args2; @@ -762,13 +726,13 @@ setup_coding_system (val, &process_coding); process_coding.dst_multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); + process_coding.src_multibyte = 0; } - process_coding.src_multibyte = 0; immediate_quit = 1; QUIT; - if (output_to_buffer) + if (0 <= fd0) { enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 }; enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN }; @@ -779,9 +743,8 @@ EMACS_INT total_read = 0; int carryover = 0; bool display_on_the_fly = display_p; - struct coding_system saved_coding; + struct coding_system saved_coding = process_coding; - saved_coding = process_coding; while (1) { /* Repeatedly read until we've filled as much as possible @@ -812,58 +775,54 @@ /* Now NREAD is the total amount of data in the buffer. */ immediate_quit = 0; - if (!NILP (buffer)) - { - if (NILP (BVAR (current_buffer, enable_multibyte_characters)) - && ! CODING_MAY_REQUIRE_DECODING (&process_coding)) - insert_1_both (buf, nread, nread, 0, 1, 0); - else - { /* We have to decode the input. */ - Lisp_Object curbuf; - ptrdiff_t count1 = SPECPDL_INDEX (); - - XSETBUFFER (curbuf, current_buffer); - /* We cannot allow after-change-functions be run - during decoding, because that might modify the - buffer, while we rely on process_coding.produced to - faithfully reflect inserted text until we - TEMP_SET_PT_BOTH below. */ - specbind (Qinhibit_modification_hooks, Qt); - decode_coding_c_string (&process_coding, - (unsigned char *) buf, nread, curbuf); - unbind_to (count1, Qnil); - if (display_on_the_fly - && CODING_REQUIRE_DETECTION (&saved_coding) - && ! CODING_REQUIRE_DETECTION (&process_coding)) - { - /* We have detected some coding system. But, - there's a possibility that the detection was - done by insufficient data. So, we give up - displaying on the fly. */ - if (process_coding.produced > 0) - del_range_2 (process_coding.dst_pos, - process_coding.dst_pos_byte, - process_coding.dst_pos - + process_coding.produced_char, - process_coding.dst_pos_byte - + process_coding.produced, 0); - display_on_the_fly = 0; - process_coding = saved_coding; - carryover = nread; - /* This is to make the above condition always - fails in the future. */ - saved_coding.common_flags - &= ~CODING_REQUIRE_DETECTION_MASK; - continue; - } - - TEMP_SET_PT_BOTH (PT + process_coding.produced_char, - PT_BYTE + process_coding.produced); - carryover = process_coding.carryover_bytes; - if (carryover > 0) - memcpy (buf, process_coding.carryover, - process_coding.carryover_bytes); + if (NILP (BVAR (current_buffer, enable_multibyte_characters)) + && ! CODING_MAY_REQUIRE_DECODING (&process_coding)) + insert_1_both (buf, nread, nread, 0, 1, 0); + else + { /* We have to decode the input. */ + Lisp_Object curbuf; + ptrdiff_t count1 = SPECPDL_INDEX (); + + XSETBUFFER (curbuf, current_buffer); + /* We cannot allow after-change-functions be run + during decoding, because that might modify the + buffer, while we rely on process_coding.produced to + faithfully reflect inserted text until we + TEMP_SET_PT_BOTH below. */ + specbind (Qinhibit_modification_hooks, Qt); + decode_coding_c_string (&process_coding, + (unsigned char *) buf, nread, curbuf); + unbind_to (count1, Qnil); + if (display_on_the_fly + && CODING_REQUIRE_DETECTION (&saved_coding) + && ! CODING_REQUIRE_DETECTION (&process_coding)) + { + /* We have detected some coding system, but the + detection may have been via insufficient data. + So give up displaying on the fly. */ + if (process_coding.produced > 0) + del_range_2 (process_coding.dst_pos, + process_coding.dst_pos_byte, + (process_coding.dst_pos + + process_coding.produced_char), + (process_coding.dst_pos_byte + + process_coding.produced), + 0); + display_on_the_fly = 0; + process_coding = saved_coding; + carryover = nread; + /* Make the above condition always fail in the future. */ + saved_coding.common_flags + &= ~CODING_REQUIRE_DETECTION_MASK; + continue; } + + TEMP_SET_PT_BOTH (PT + process_coding.produced_char, + PT_BYTE + process_coding.produced); + carryover = process_coding.carryover_bytes; + if (carryover > 0) + memcpy (buf, process_coding.carryover, + process_coding.carryover_bytes); } if (process_coding.mode & CODING_MODE_LAST_BLOCK) @@ -882,7 +841,7 @@ first = 0; redisplay_preserve_echo_area (1); /* This variable might have been set to 0 for code - detection. In that case, we set it back to 1 because + detection. In that case, set it back to 1 because we should have already detected a coding system. */ display_on_the_fly = 1; } @@ -901,7 +860,7 @@ #ifndef MSDOS /* Wait for it to terminate, unless it already has. */ - wait_for_termination (pid, &status, !output_to_buffer); + wait_for_termination (pid, &status, fd0 < 0); #endif immediate_quit = 0; @@ -931,37 +890,18 @@ return make_number (WEXITSTATUS (status)); } -static void -delete_temp_file (Lisp_Object name) -{ - /* Suppress jka-compr handling, etc. */ - ptrdiff_t count = SPECPDL_INDEX (); - specbind (intern ("file-name-handler-alist"), Qnil); -#ifdef WINDOWSNT - /* If this is called when the subprocess didn't exit yet, the - attempt to delete its input file will fail. In that case, we - schedule the file for deletion when the subprocess exits. This - is the 2nd part of handling this situation; see the call to - record_infile in call-process above, for the first part. */ - if (!internal_delete_file (name)) - { - Lisp_Object encoded_file = ENCODE_FILE (name); - - record_pending_deletion (SSDATA (encoded_file)); - } -#else - internal_delete_file (name); -#endif - unbind_to (count, Qnil); -} - /* Create a temporary file suitable for storing the input data of call-process-region. NARGS and ARGS are the same as for - call-process-region. */ + call-process-region. Store into *FILENAME_STRING_PTR a Lisp string + naming the file, and return a file descriptor for reading. + Unwind-protect the file, so that the file descriptor will be closed + and the file removed when the caller unwinds the specpdl stack. */ -static Lisp_Object -create_temp_file (ptrdiff_t nargs, Lisp_Object *args) +static int +create_temp_file (ptrdiff_t nargs, Lisp_Object *args, + Lisp_Object *filename_string_ptr) { + int fd; struct gcpro gcpro1; Lisp_Object filename_string; Lisp_Object val, start, end; @@ -988,6 +928,7 @@ { Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir); char *tempfile; + ptrdiff_t count; #ifdef WINDOWSNT /* Cannot use the result of Fexpand_file_name, because it @@ -1008,15 +949,14 @@ GCPRO1 (filename_string); tempfile = SSDATA (filename_string); - { - int fd = mkostemp (tempfile, O_CLOEXEC); - if (fd < 0) - report_file_error ("Failed to open temporary file using pattern", - pattern); - emacs_close (fd); - } - - record_unwind_protect (delete_temp_file, filename_string); + count = SPECPDL_INDEX (); + record_unwind_protect_nothing (); + fd = mkostemp (tempfile, O_CLOEXEC); + if (fd < 0) + report_file_error ("Failed to open temporary file using pattern", + pattern); + set_unwind_protect (count, delete_temp_file, filename_string); + record_unwind_protect_int (close_file_unwind, fd); } start = args[0]; @@ -1047,15 +987,20 @@ /* POSIX lets mk[s]temp use "."; don't invoke jka-compr if we happen to get a ".Z" suffix. */ specbind (intern ("file-name-handler-alist"), Qnil); - Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil); + write_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil, fd); unbind_to (count1, Qnil); } + if (lseek (fd, 0, SEEK_SET) < 0) + report_file_error ("Setting file position", filename_string); + /* Note that Fcall_process takes care of binding coding-system-for-read. */ - RETURN_UNGCPRO (filename_string); + *filename_string_ptr = filename_string; + UNGCPRO; + return fd; } DEFUN ("call-process-region", Fcall_process_region, Scall_process_region, @@ -1085,12 +1030,13 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { - struct gcpro gcpro1; - Lisp_Object infile; + struct gcpro gcpro1, gcpro2; + Lisp_Object infile, val; ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object start = args[0]; Lisp_Object end = args[1]; bool empty_input; + int fd; if (STRINGP (start)) empty_input = SCHARS (start) == 0; @@ -1104,8 +1050,19 @@ empty_input = XINT (start) == XINT (end); } - infile = empty_input ? Qnil : create_temp_file (nargs, args); - GCPRO1 (infile); + if (!empty_input) + fd = create_temp_file (nargs, args, &infile); + else + { + infile = Qnil; + fd = emacs_open (NULL_DEVICE, O_RDONLY, 0); + if (fd < 0) + report_file_error ("Opening null device", Qnil); + record_unwind_protect_int (close_file_unwind, fd); + } + + val = infile; + GCPRO2 (infile, val); if (nargs > 3 && !NILP (args[3])) Fdelete_region (start, end); @@ -1122,7 +1079,17 @@ } args[1] = infile; - RETURN_UNGCPRO (unbind_to (count, Fcall_process (nargs, args))); + val = call_process (nargs, args, fd); + + if (!empty_input && 4 < nargs + && (INTEGERP (CONSP (args[4]) ? XCAR (args[4]) : args[4]))) + { + record_deleted_pid (synch_process_pid, infile); + synch_process_pid = 0; + clear_unwind_protect (count); + } + + RETURN_UNGCPRO (unbind_to (count, val)); } #ifndef WINDOWSNT @@ -1683,6 +1650,11 @@ #endif staticpro (&Vtemp_file_name_pattern); +#ifdef MSDOS + synch_process_tempfile = make_number (0); + staticpro (&synch_process_tempfile); +#endif + DEFVAR_LISP ("shell-file-name", Vshell_file_name, doc: /* File name to load inferior shells from. Initialized from the SHELL environment variable, or to a system-dependent === modified file 'src/eval.c' --- src/eval.c 2013-08-02 21:16:33 +0000 +++ src/eval.c 2013-08-12 07:12:07 +0000 @@ -3302,6 +3302,16 @@ previous value without invoking it. */ void +set_unwind_protect (ptrdiff_t count, void (*func) (Lisp_Object), + Lisp_Object arg) +{ + union specbinding *p = specpdl + count; + p->unwind.kind = SPECPDL_UNWIND; + p->unwind.func = func; + p->unwind.arg = arg; +} + +void set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) { union specbinding *p = specpdl + count; === modified file 'src/fileio.c' --- src/fileio.c 2013-08-05 04:14:43 +0000 +++ src/fileio.c 2013-08-12 07:12:07 +0000 @@ -4746,25 +4746,39 @@ This calls `write-region-annotate-functions' at the start, and `write-region-post-annotation-function' at the end. */) - (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) -{ - int desc; + (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, + Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) +{ + return write_region (start, end, filename, append, visit, lockname, mustbenew, + -1); +} + +/* Like Fwrite_region, except that if DESC is nonnegative, it is a file + descriptor for FILENAME, so do not open or close FILENAME. */ + +Lisp_Object +write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, + Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, + Lisp_Object mustbenew, int desc) +{ int open_flags; int mode; off_t offset IF_LINT (= 0); + bool open_and_close_file = desc < 0; bool ok; int save_errno = 0; const char *fn; struct stat st; EMACS_TIME modtime; ptrdiff_t count = SPECPDL_INDEX (); - ptrdiff_t count1; + ptrdiff_t count1 IF_LINT (= 0); Lisp_Object handler; Lisp_Object visit_file; Lisp_Object annotations; Lisp_Object encoded_filename; bool visiting = (EQ (visit, Qt) || STRINGP (visit)); bool quietly = !NILP (visit); + bool file_locked = 0; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; struct buffer *given_buffer; struct coding_system coding; @@ -4832,7 +4846,6 @@ record_unwind_protect (build_annotations_unwind, Vwrite_region_annotation_buffers); Vwrite_region_annotation_buffers = list1 (Fcurrent_buffer ()); - count1 = SPECPDL_INDEX (); given_buffer = current_buffer; @@ -4871,8 +4884,11 @@ coding.mode |= CODING_MODE_SELECTIVE_DISPLAY; #ifdef CLASH_DETECTION - if (!auto_saving) - lock_file (lockname); + if (open_and_close_file && !auto_saving) + { + lock_file (lockname); + file_locked = 1; + } #endif /* CLASH_DETECTION */ encoded_filename = ENCODE_FILE (filename); @@ -4889,20 +4905,24 @@ mode = auto_saving ? auto_save_mode_bits : 0666; #endif - desc = emacs_open (fn, open_flags, mode); - - if (desc < 0) + if (open_and_close_file) { - int open_errno = errno; + desc = emacs_open (fn, open_flags, mode); + if (desc < 0) + { + int open_errno = errno; #ifdef CLASH_DETECTION - if (!auto_saving) unlock_file (lockname); + if (file_locked) + unlock_file (lockname); #endif /* CLASH_DETECTION */ - UNGCPRO; - report_file_errno ("Opening output file", filename, open_errno); + UNGCPRO; + report_file_errno ("Opening output file", filename, open_errno); + } + + count1 = SPECPDL_INDEX (); + record_unwind_protect_int (close_file_unwind, desc); } - record_unwind_protect_int (close_file_unwind, desc); - if (NUMBERP (append)) { off_t ret = lseek (desc, offset, SEEK_SET); @@ -4910,7 +4930,8 @@ { int lseek_errno = errno; #ifdef CLASH_DETECTION - if (!auto_saving) unlock_file (lockname); + if (file_locked) + unlock_file (lockname); #endif /* CLASH_DETECTION */ UNGCPRO; report_file_errno ("Lseek error", filename, lseek_errno); @@ -4945,9 +4966,9 @@ immediate_quit = 0; - /* fsync is not crucial for auto-save files, since they might lose - some work anyway. */ - if (!auto_saving && !write_region_inhibit_fsync) + /* fsync is not crucial for temporary files. Nor for auto-save + files, since they might lose some work anyway. */ + if (open_and_close_file && !auto_saving && !write_region_inhibit_fsync) { /* Transfer data and metadata to disk, retrying if interrupted. fsync can report a write failure here, e.g., due to disk full @@ -4971,12 +4992,15 @@ ok = 0, save_errno = errno; } - /* NFS can report a write failure now. */ - if (emacs_close (desc) < 0) - ok = 0, save_errno = errno; + if (open_and_close_file) + { + /* NFS can report a write failure now. */ + if (emacs_close (desc) < 0) + ok = 0, save_errno = errno; - /* Discard the unwind protect for close_file_unwind. */ - specpdl_ptr = specpdl + count1; + /* Discard the unwind protect for close_file_unwind. */ + specpdl_ptr = specpdl + count1; + } /* Some file systems have a bug where st_mtime is not updated properly after a write. For example, CIFS might not see the @@ -5052,7 +5076,7 @@ unbind_to (count, Qnil); #ifdef CLASH_DETECTION - if (!auto_saving) + if (file_locked) unlock_file (lockname); #endif /* CLASH_DETECTION */ === modified file 'src/lisp.h' --- src/lisp.h 2013-08-11 19:43:36 +0000 +++ src/lisp.h 2013-08-12 07:12:07 +0000 @@ -3746,11 +3746,12 @@ Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *)); extern void specbind (Lisp_Object, Lisp_Object); extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); +extern void record_unwind_protect_ptr (void (*) (void *), void *); extern void record_unwind_protect_int (void (*) (int), int); -extern void record_unwind_protect_ptr (void (*) (void *), void *); extern void record_unwind_protect_void (void (*) (void)); extern void record_unwind_protect_nothing (void); extern void clear_unwind_protect (ptrdiff_t); +extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object); extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *); extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object); extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); @@ -3830,6 +3831,9 @@ extern Lisp_Object Qinsert_file_contents; extern Lisp_Object Qfile_name_history; extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); +extern Lisp_Object write_region (Lisp_Object, Lisp_Object, Lisp_Object, + Lisp_Object, Lisp_Object, Lisp_Object, + Lisp_Object, int); EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ extern void close_file_unwind (int); extern void fclose_unwind (void *); === modified file 'src/process.c' --- src/process.c 2013-08-11 01:30:20 +0000 +++ src/process.c 2013-08-12 07:12:07 +0000 @@ -92,6 +92,7 @@ #include #include +#include #endif /* subprocesses */ @@ -722,6 +723,8 @@ non-Lisp data, so do it only for slots which should not be zero. */ p->infd = -1; p->outfd = -1; + for (i = 0; i < PROCESS_OPEN_FDS; i++) + p->open_fd[i] = -1; #ifdef HAVE_GNUTLS p->gnutls_initstage = GNUTLS_STAGE_EMPTY; @@ -818,13 +821,17 @@ treated by the SIGCHLD handler and waitpid has been invoked on them; otherwise they might fill up the kernel's process table. - Some processes created by call-process are also put onto this list. */ + Some processes created by call-process are also put onto this list. + + Members of this list are (process-ID . filename) pairs. The + process-ID is a number; the filename, if a string, is a file that + needs to be removed after the process exits. */ static Lisp_Object deleted_pid_list; void -record_deleted_pid (pid_t pid) +record_deleted_pid (pid_t pid, Lisp_Object filename) { - deleted_pid_list = Fcons (make_fixnum_or_float (pid), + deleted_pid_list = Fcons (Fcons (make_fixnum_or_float (pid), filename), /* GC treated elements set to nil. */ Fdelq (Qnil, deleted_pid_list)); @@ -852,7 +859,7 @@ else { if (p->alive) - record_kill_process (p); + record_kill_process (p, Qnil); if (p->infd >= 0) { @@ -1605,17 +1612,45 @@ remove_process (proc); } +/* If *FD_ADDR is nonnegative, close it, and mark it as closed. */ + +static void +close_process_fd (int *fd_addr) +{ + int fd = *fd_addr; + if (0 <= fd) + { + *fd_addr = -1; + emacs_close (fd); + } +} + +/* Indexes of file descriptors in open_fds. */ +enum + { + /* The pipe from Emacs to its subprocess. */ + SUBPROCESS_STDIN, + WRITE_TO_SUBPROCESS, + + /* The main pipe from the subprocess to Emacs. */ + READ_FROM_SUBPROCESS, + SUBPROCESS_STDOUT, + + /* The pipe from the subprocess to Emacs that is closed when the + subprocess execs. */ + READ_FROM_EXEC_MONITOR, + EXEC_MONITOR_OUTPUT + }; + +verify (PROCESS_OPEN_FDS == EXEC_MONITOR_OUTPUT + 1); static void create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) { + struct Lisp_Process *p = XPROCESS (process); int inchannel, outchannel; pid_t pid; int vfork_errno; - int sv[2]; -#ifndef WINDOWSNT - int wait_child_setup[2]; -#endif int forkin, forkout; bool pty_flag = 0; char pty_name[PTY_NAME_SIZE]; @@ -1629,6 +1664,7 @@ if (inchannel >= 0) { + p->open_fd[READ_FROM_SUBPROCESS] = inchannel; #if ! defined (USG) || defined (USG_SUBTTY_WORKS) /* On most USG systems it does not work to open the pty's tty here, then close it and reopen it in the child. */ @@ -1637,6 +1673,7 @@ forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); if (forkin < 0) report_file_error ("Opening pty", Qnil); + p->open_fd[SUBPROCESS_STDIN] = forkin; #else forkin = forkout = -1; #endif /* not USG, or USG_SUBTTY_WORKS */ @@ -1645,23 +1682,17 @@ } else { - if (emacs_pipe (sv) != 0) + if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0 + || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0) report_file_error ("Creating pipe", Qnil); - inchannel = sv[0]; - forkout = sv[1]; - if (emacs_pipe (sv) != 0) - { - int pipe_errno = errno; - emacs_close (inchannel); - emacs_close (forkout); - report_file_errno ("Creating pipe", Qnil, pipe_errno); - } - outchannel = sv[1]; - forkin = sv[0]; + forkin = p->open_fd[SUBPROCESS_STDIN]; + outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; + inchannel = p->open_fd[READ_FROM_SUBPROCESS]; + forkout = p->open_fd[SUBPROCESS_STDOUT]; } #ifndef WINDOWSNT - if (emacs_pipe (wait_child_setup) != 0) + if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0) report_file_error ("Creating pipe", Qnil); #endif @@ -1670,16 +1701,16 @@ /* Record this as an active process, with its channels. */ chan_process[inchannel] = process; - XPROCESS (process)->infd = inchannel; - XPROCESS (process)->outfd = outchannel; + p->infd = inchannel; + p->outfd = outchannel; /* Previously we recorded the tty descriptor used in the subprocess. It was only used for getting the foreground tty process, so now we just reopen the device (see emacs_get_tty_pgrp) as this is more portable (see USG_SUBTTY_WORKS above). */ - XPROCESS (process)->pty_flag = pty_flag; - pset_status (XPROCESS (process), Qrun); + p->pty_flag = pty_flag; + pset_status (p, Qrun); FD_SET (inchannel, &input_wait_mask); FD_SET (inchannel, &non_keyboard_wait_mask); @@ -1699,25 +1730,21 @@ { Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; - Lisp_Object volatile process_volatile = process; char **volatile new_argv_volatile = new_argv; int volatile forkin_volatile = forkin; int volatile forkout_volatile = forkout; - int volatile wait_child_setup_0_volatile = wait_child_setup[0]; - int volatile wait_child_setup_1_volatile = wait_child_setup[1]; + struct Lisp_Process *p_volatile = p; pid = vfork (); encoded_current_dir = encoded_current_dir_volatile; lisp_pty_name = lisp_pty_name_volatile; - process = process_volatile; new_argv = new_argv_volatile; forkin = forkin_volatile; forkout = forkout_volatile; - wait_child_setup[0] = wait_child_setup_0_volatile; - wait_child_setup[1] = wait_child_setup_1_volatile; + p = p_volatile; - pty_flag = XPROCESS (process)->pty_flag; + pty_flag = p->pty_flag; } if (pid == 0) @@ -1833,42 +1860,42 @@ /* Back in the parent process. */ vfork_errno = errno; - XPROCESS (process)->pid = pid; + p->pid = pid; if (pid >= 0) - XPROCESS (process)->alive = 1; + p->alive = 1; /* Stop blocking in the parent. */ unblock_child_signal (); unblock_input (); - if (forkin >= 0) - emacs_close (forkin); - if (forkin != forkout && forkout >= 0) - emacs_close (forkout); - if (pid < 0) report_file_errno ("Doing vfork", Qnil, vfork_errno); else { /* vfork succeeded. */ + /* Close the pipe ends that the child uses, or the child's pty. */ + close_process_fd (&p->open_fd[SUBPROCESS_STDIN]); + close_process_fd (&p->open_fd[SUBPROCESS_STDOUT]); + #ifdef WINDOWSNT register_child (pid, inchannel); #endif /* WINDOWSNT */ - pset_tty_name (XPROCESS (process), lisp_pty_name); + pset_tty_name (p, lisp_pty_name); #ifndef WINDOWSNT /* Wait for child_setup to complete in case that vfork is - actually defined as fork. The descriptor wait_child_setup[1] + actually defined as fork. The descriptor + XPROCESS (proc)->open_fd[EXEC_MOINTOR_OUTPUT] of a pipe is closed at the child side either by close-on-exec on successful execve or the _exit call in child_setup. */ { char dummy; - emacs_close (wait_child_setup[1]); - emacs_read (wait_child_setup[0], &dummy, 1); - emacs_close (wait_child_setup[0]); + close_process_fd (&p->open_fd[EXEC_MONITOR_OUTPUT]); + emacs_read (p->open_fd[READ_FROM_EXEC_MONITOR], &dummy, 1); + close_process_fd (&p->open_fd[READ_FROM_EXEC_MONITOR]); } #endif } @@ -1877,16 +1904,13 @@ static void create_pty (Lisp_Object process) { + struct Lisp_Process *p = XPROCESS (process); char pty_name[PTY_NAME_SIZE]; - int inchannel, outchannel; - - inchannel = outchannel = -1; - - if (!NILP (Vprocess_connection_type)) - outchannel = inchannel = allocate_pty (pty_name); - - if (inchannel >= 0) + int pty_fd = NILP (Vprocess_connection_type) ? -1 : allocate_pty (pty_name); + + if (pty_fd >= 0) { + p->open_fd[SUBPROCESS_STDIN] = pty_fd; #if ! defined (USG) || defined (USG_SUBTTY_WORKS) /* On most USG systems it does not work to open the pty's tty here, then close it and reopen it in the child. */ @@ -1895,6 +1919,7 @@ int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); if (forkout < 0) report_file_error ("Opening pty", Qnil); + p->open_fd[WRITE_TO_SUBPROCESS] = forkout; #if defined (DONT_REOPEN_PTY) /* In the case that vfork is defined as fork, the parent process (Emacs) may send some data before the child process completes @@ -1903,33 +1928,32 @@ #endif /* DONT_REOPEN_PTY */ #endif /* not USG, or USG_SUBTTY_WORKS */ - fcntl (inchannel, F_SETFL, O_NONBLOCK); - fcntl (outchannel, F_SETFL, O_NONBLOCK); + fcntl (pty_fd, F_SETFL, O_NONBLOCK); /* Record this as an active process, with its channels. As a result, child_setup will close Emacs's side of the pipes. */ - chan_process[inchannel] = process; - XPROCESS (process)->infd = inchannel; - XPROCESS (process)->outfd = outchannel; + chan_process[pty_fd] = process; + p->infd = pty_fd; + p->outfd = pty_fd; /* Previously we recorded the tty descriptor used in the subprocess. It was only used for getting the foreground tty process, so now we just reopen the device (see emacs_get_tty_pgrp) as this is more portable (see USG_SUBTTY_WORKS above). */ - XPROCESS (process)->pty_flag = 1; - pset_status (XPROCESS (process), Qrun); + p->pty_flag = 1; + pset_status (p, Qrun); setup_process_coding_systems (process); - FD_SET (inchannel, &input_wait_mask); - FD_SET (inchannel, &non_keyboard_wait_mask); - if (inchannel > max_process_desc) - max_process_desc = inchannel; + FD_SET (pty_fd, &input_wait_mask); + FD_SET (pty_fd, &non_keyboard_wait_mask); + if (pty_fd > max_process_desc) + max_process_desc = pty_fd; - pset_tty_name (XPROCESS (process), build_string (pty_name)); + pset_tty_name (p, build_string (pty_name)); } - XPROCESS (process)->pid = -2; + p->pid = -2; } @@ -2535,6 +2559,7 @@ p = XPROCESS (proc); fd = serial_open (port); + p->open_fd[SUBPROCESS_STDIN] = fd; p->infd = fd; p->outfd = fd; if (fd > max_process_desc) @@ -3297,12 +3322,6 @@ } #endif - /* Discard the unwind protect for closing S, if any. */ - specpdl_ptr = specpdl + count1; - - /* Unwind bind_polling_period and request_sigio. */ - unbind_to (count, Qnil); - if (s < 0) { /* If non-blocking got this far - and failed - assume non-blocking is @@ -3344,8 +3363,17 @@ if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) pset_command (p, Qt); p->pid = 0; + + p->open_fd[SUBPROCESS_STDIN] = inch; p->infd = inch; p->outfd = outch; + + /* Discard the unwind protect for closing S, if any. */ + specpdl_ptr = specpdl + count1; + + /* Unwind bind_polling_period and request_sigio. */ + unbind_to (count, Qnil); + if (is_server && socktype != SOCK_DGRAM) pset_status (p, Qlisten); @@ -3784,17 +3812,15 @@ static void deactivate_process (Lisp_Object proc) { - register int inchannel, outchannel; - register struct Lisp_Process *p = XPROCESS (proc); + int inchannel; + struct Lisp_Process *p = XPROCESS (proc); + int i; #ifdef HAVE_GNUTLS /* Delete GnuTLS structures in PROC, if any. */ emacs_gnutls_deinit (proc); #endif /* HAVE_GNUTLS */ - inchannel = p->infd; - outchannel = p->outfd; - #ifdef ADAPTIVE_READ_BUFFERING if (p->read_output_delay > 0) { @@ -3805,16 +3831,17 @@ } #endif + inchannel = p->infd; + + /* Beware SIGCHLD hereabouts. */ + if (inchannel >= 0) + flush_pending_output (inchannel); + + for (i = 0; i < PROCESS_OPEN_FDS; i++) + close_process_fd (&p->open_fd[i]); + if (inchannel >= 0) { - /* Beware SIGCHLD hereabouts. */ - flush_pending_output (inchannel); - emacs_close (inchannel); - if (outchannel >= 0 && outchannel != inchannel) - emacs_close (outchannel); - - p->infd = -1; - p->outfd = -1; #ifdef DATAGRAM_SOCKETS if (DATAGRAM_CHAN_P (inchannel)) { @@ -4095,6 +4122,7 @@ /* Discard the unwind protect for closing S. */ specpdl_ptr = specpdl + count; + p->open_fd[SUBPROCESS_STDIN] = s; p->infd = s; p->outfd = s; pset_status (p, Qrun); @@ -6014,7 +6042,8 @@ } else { - int old_outfd, new_outfd; + int old_outfd = XPROCESS (proc)->outfd; + int new_outfd; #ifdef HAVE_SHUTDOWN /* If this is a network connection, or socketpair is used @@ -6022,18 +6051,15 @@ (In some old system, shutdown to socketpair doesn't work. Then we just can't win.) */ if (EQ (XPROCESS (proc)->type, Qnetwork) - || XPROCESS (proc)->outfd == XPROCESS (proc)->infd) - shutdown (XPROCESS (proc)->outfd, 1); - /* In case of socketpair, outfd == infd, so don't close it. */ - if (XPROCESS (proc)->outfd != XPROCESS (proc)->infd) - emacs_close (XPROCESS (proc)->outfd); -#else /* not HAVE_SHUTDOWN */ - emacs_close (XPROCESS (proc)->outfd); -#endif /* not HAVE_SHUTDOWN */ + || XPROCESS (proc)->infd == old_outfd) + shutdown (old_outfd, 1); +#endif + close_process_fd (&XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS]); new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); if (new_outfd < 0) - emacs_abort (); - old_outfd = XPROCESS (proc)->outfd; + report_file_error ("Opening null device", Qnil); + XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS] = new_outfd; + XPROCESS (proc)->outfd = new_outfd; if (!proc_encode_coding_system[new_outfd]) proc_encode_coding_system[new_outfd] @@ -6042,8 +6068,6 @@ = *proc_encode_coding_system[old_outfd]; memset (proc_encode_coding_system[old_outfd], 0, sizeof (struct coding_system)); - - XPROCESS (proc)->outfd = new_outfd; } return process; } @@ -6120,7 +6144,8 @@ bool all_pids_are_fixnums = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); - Lisp_Object xpid = XCAR (tail); + Lisp_Object head = XCAR (tail); + Lisp_Object xpid = XCAR (head); if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) { pid_t deleted_pid; @@ -6129,7 +6154,11 @@ else deleted_pid = XFLOAT_DATA (xpid); if (child_status_changed (deleted_pid, 0, 0)) - XSETCAR (tail, Qnil); + { + if (STRINGP (XCDR (head))) + unlink (SSDATA (XCDR (head))); + XSETCAR (tail, Qnil); + } } } === modified file 'src/process.h' --- src/process.h 2013-07-09 07:04:48 +0000 +++ src/process.h 2013-08-12 07:12:07 +0000 @@ -31,6 +31,11 @@ # define PROCESS_INLINE INLINE #endif +/* Bound on number of file descriptors opened on behalf of a process, + that need to be closed. */ + +enum { PROCESS_OPEN_FDS = 6 }; + /* This structure records information about a subprocess or network connection. */ @@ -115,6 +120,9 @@ int infd; /* Descriptor by which we write to this process */ int outfd; + /* Descriptors that were created for this process and that need + closing. Unused entries are negative. */ + int open_fd[PROCESS_OPEN_FDS]; /* Event-count of last event in which this process changed status. */ EMACS_INT tick; /* Event-count of last such event reported. */ @@ -210,13 +218,16 @@ extern void block_child_signal (void); extern void unblock_child_signal (void); -extern void record_kill_process (struct Lisp_Process *); +extern void record_kill_process (struct Lisp_Process *, Lisp_Object); -/* Defined in process.c. */ +/* Defined in sysdep.c. */ extern Lisp_Object list_system_processes (void); extern Lisp_Object system_process_attributes (Lisp_Object); +/* Defined in process.c. */ + +extern void record_deleted_pid (pid_t, Lisp_Object); extern void hold_keyboard_input (void); extern void unhold_keyboard_input (void); extern bool kbd_on_hold_p (void); === modified file 'src/syswait.h' --- src/syswait.h 2013-01-02 16:13:04 +0000 +++ src/syswait.h 2013-08-12 07:12:07 +0000 @@ -52,9 +52,6 @@ #define WTERMSIG(status) ((status) & 0x7f) #endif -/* Defined in process.c. */ -extern void record_deleted_pid (pid_t); - /* Defined in sysdep.c. */ extern void wait_for_termination (pid_t, int *, bool); extern pid_t child_status_changed (pid_t, int *, int); ------------------------------------------------------------ revno: 113812 committer: Katsumi Yamaoka branch nick: trunk timestamp: Mon 2013-08-12 06:32:15 +0000 message: lisp/gnus/ChangeLog: Fix typo diff: === modified file 'lisp/gnus/ChangeLog' --- lisp/gnus/ChangeLog 2013-08-12 05:59:47 +0000 +++ lisp/gnus/ChangeLog 2013-08-12 06:32:15 +0000 @@ -1,7 +1,7 @@ 2013-08-12 Katsumi Yamaoka * mm-decode.el (mm-display-external): Run a timer for the temp files - deletion after a viwer exits; add a deletion timer for the needsterm + deletion after a viewer exits; add a deletion timer for the needsterm case, too. * mm-decode.el (mm-display-external): Try to delete temporary files by