branch: elpa/logview commit 0a1b3a8268a45a0c5a682bc04546dec056fb1950 Author: Paul Pogonyshev <pogonys...@gmail.com> Commit: Paul Pogonyshev <pogonys...@gmail.com>
Prevent certain errors on Emacs 29 (up to a full freeze) by preventively disabling its long-line optimization; fail fast if that doesn't help. --- logview.el | 62 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/logview.el b/logview.el index a38feab48a..a0819423cb 100644 --- a/logview.el +++ b/logview.el @@ -644,6 +644,7 @@ this face is used." (defvar-local logview--custom-submode-guessed-with 0) +;; Don't access these as variables directly, use functions with the same name instead. (defvar-local logview--point-min nil) (defvar-local logview--point-max nil) @@ -859,13 +860,33 @@ works for \\[logview-set-navigation-view] and \\[logview-highlight-view-entries] (with-silent-modifications ,@body)))) -(defmacro logview--std-temporarily-widening (&rest body) +(defmacro logview--temporarily-widening (&rest body) + "Execute BODY with the current buffer fully widened. +Original point restrictions, if any, will not be possible to find +inside BODY. In most cases (also if not sure) you should use +macro `logview--std-temporarily-widening' instead." (declare (indent 0) (debug t)) `(save-restriction - (let ((logview--point-min (logview--point-min)) - (logview--point-max (logview--point-max))) - (widen) - ,@body))) + (widen) + ,@(when (>= emacs-major-version 29) + ;; It is better to fail hard now than to face an arbitrary failure later. In + ;; particular, an infinite loop in fontification code can irreversibly freeze + ;; Emacs, but this is of course "not a bug": + ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57804 + `((unless (and (= (point-min) 1) (= (point-max) (1+ (buffer-size)))) + (error "Logview is incompatible with locked narrowing; see https://github.com/doublep/logview#locked-narrowing")))) + ,@body)) + +(defmacro logview--std-temporarily-widening (&rest body) + "Execute BODY with the current buffer fully widened. +Original point restrictions are available as return values of +functions `logview--point-min' and `logview--point-max'. This +macro can be nested, with inner calls not changing results of the +two functions (available since the first call) further." + (declare (indent 0) (debug t)) + `(let ((logview--point-min (logview--point-min)) + (logview--point-max (logview--point-max))) + (logview--temporarily-widening ,@body))) (defmacro logview--locate-current-entry (entry start &rest body) (declare (indent 2) (debug (symbolp symbolp body))) @@ -1114,9 +1135,16 @@ interfere with editing) or if submode wasn't guessed successfully.") +;; Emacs 29 (snapshots); need to set it to nil. +(defvar long-line-threshold) + ;;;###autoload (define-derived-mode logview-mode nil "Logview" "Major mode for viewing and filtering various log files." + ;; Logview is incompatible with locked narrowing of Emacs 29. Set this variable in hope + ;; this prevents it from ever happening. See `logview--temporarily-widening'. + (when (boundp 'long-line-threshold) + (setq-local long-line-threshold nil)) (logview--update-keymap) (add-hook 'read-only-mode-hook #'logview--update-keymap nil t) (setq font-lock-defaults (copy-sequence logview-font-lock-defaults)) @@ -2707,8 +2735,7 @@ returns non-nil." (if (and (>= temporary-size reassurance-chars) (string= (buffer-substring-no-properties 1 (1+ reassurance-chars)) (with-current-buffer buffer - (save-restriction - (widen) + (logview--std-temporarily-widening (buffer-substring-no-properties compare-from size))))) (if (= temporary-size reassurance-chars) (message "Backing file %s hasn't grown" file) @@ -2718,8 +2745,7 @@ returns non-nil." ;; This is to avoid unnecessary confirmation about ;; modifying a buffer with externally changed file. (buffer-file-name nil)) - (save-restriction - (widen) + (logview--std-temporarily-widening (save-excursion (goto-char (point-max)) (insert-buffer-substring-no-properties temporary (1+ reassurance-chars) (1+ temporary-size)))) @@ -2732,16 +2758,17 @@ returns non-nil." ;;; Internal functions (except helpers for specific command groups). -(defvar inhibit-message) - (defmacro logview--internal-log (format-string &rest arguments) `(let ((inhibit-message t)) (message ,format-string ,@arguments))) (defun logview--guess-submode () (save-excursion - (save-restriction - (widen) + ;; Need access to the buffer start, regardless of any narrowing. Also, don't want + ;; original narrowing to have any effect on anything (see uses of corresponding + ;; functions that access it; not even sure they are even called from here, but that + ;; doesn't matter), that's why not `std'. + (logview--temporarily-widening (let ((line-number 0) (remaining-attemps (if (and (integerp logview-max-promising-lines) (> logview-max-promising-lines 0)) logview-max-promising-lines @@ -3672,7 +3699,10 @@ This list is preserved across Emacs session in (defun logview--fontify-region (region-start region-end loudly) (when (logview-initialized-p) - (logview--std-temporarily-widening + ;; We are basically managing narrowing indirectly, by not fontifying further than + ;; `region-end' (possibly expanded). Not using `std' here to prevent + ;; `logview--iterate-entries-forward' from stopping early because of outer narrowing. + (logview--temporarily-widening ;; We are very fast. Don't fontify too little to avoid overhead. ;; FIXME: See `font-lock-extend-region-functions'. Might want to reuse that instead. (when (and (< region-end (point-max)) (not (get-text-property (1+ region-end) 'fontified))) @@ -3916,9 +3946,9 @@ This list is preserved across Emacs session in (defun logview-filter-edit--font-lock-region (region-begin region-end &optional _old-length) (save-excursion (save-match-data - (save-restriction + ;; Not even in a Logview mode buffer, not using `std'. + (logview--temporarily-widening (with-silent-modifications - (widen) (goto-char region-begin) (forward-line 0) ;; Never try to parse from the middle of a multiline filter.