Package: auctex
Version: 14.1.2 (current GNU ELPA)
Emacs: GNU Emacs 29.3
Ghostscript: 10.02.1 (Ubuntu 24.04.4 LTS, package 10.02.1~dfsg1-0ubuntu7.8)
OS: Ubuntu 24.04.4 LTS
=====================================================================
SUMMARY
=====================================================================
With TeX-PDF-mode enabled (previews generated from PDF via
preview-start-pdf2dsc / Ghostscript's native PDF interpreter, rather
than from DVI via dvipng), previewing more than one math snippet in a
single batch reliably crashes every preview in that batch with a
Ghostscript "/typecheck in --setfileposition--" error. A single,
isolated snippet does not crash via this path (though it also does not
produce a usable image -- see "Secondary issue" below).
This reproduces on a plain `article`-class document with amsmath only
-- no custom classes, macros, or packages are required.
I found and fixed one confirmed contributing bug (a redundant
duplicate "dup" in the generated PostScript, in preview-gs-transact),
verified by comparing the Ghostscript error's operand-stack contents
before and after the fix (see below). After that fix, the crash still
occurs, but with less redundant garbage on the stack, which points to
a second, deeper issue interacting with Ghostscript's native PDF
interpreter operators (runpdfbegin/dopdfpages) that the decades-old
per-page splitting technique in preview.el was apparently never
designed to account for.
=====================================================================
STEPS TO REPRODUCE
=====================================================================
1. Ensure `TeX-PDF-mode` is t (default in many configs; compiles with
pdflatex rather than latex+dvips).
2. Set:
(setq preview-pdf-color-adjust-method 'compatible)
(This is one of the three documented values for this variable. It
was tried as a workaround for a separate, unrelated problem: the
default t value produces images that render but are invisible
against a non-default/dark Emacs theme -- see "Related observation"
below. 'compatible was expected to be the safe historical fallback.)
3. Create a minimal file, e.g. repro.tex:
\documentclass{article}
\usepackage{amsmath}
\begin{document}
\begin{equation}
E = mc^2
\end{equation}
\begin{equation}
a^2 + b^2 = c^2
\end{equation}
\begin{equation}
\int_0^\infty e^{-x^2}\,dx = \frac{\sqrt{\pi}}{2}
\end{equation}
\begin{equation}
\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0}
\end{equation}
\begin{equation}
F = G\frac{m_1 m_2}{r^2}
\end{equation}
\begin{equation}
x_n = x_{n-1} + d
\end{equation}
\begin{equation}
\sum_{k=1}^{n} k = \frac{n(n+1)}{2}
\end{equation}
\begin{equation}
\frac{d}{dx}\sin(x) = \cos(x)
\end{equation}
\end{document}
4. Open it in Emacs with AUCTeX, run `preview-buffer` (C-c C-p C-b).
5. When prompted "Cache preamble? ", the answer does not matter --
tried both y and n, byte-for-byte identical crash and operand
stack in both cases (see "Ruled out" below).
RESULT: every one of the 8 equations shows a broken-preview icon.
Ghostscript's error buffer shows (redacted only for temp-dir name,
which changes per run):
/usr/bin/gs -sOutputFile=_region_.prv/tmpE86hSz/pr1-8.png -q \
-dDELAYSAFER -dNOPAUSE -DNOPLATFONTS -dPrinted -dTextAlphaBits=4 \
-dGraphicsAlphaBits=4 -sDEVICE=png16m -r146.304x144.727
GS>...(preamble omitted)...
(_region_.prv/tmpE86hSz/preview.dsc)(r)file /.preview-ST 1 index def
dup 0 setfileposition 654()/SubFileDecode filter cvx exec .preview-ST
dup 654 setfileposition 53()/SubFileDecode filter cvx<<>>preview-do
Error: /typecheck in --setfileposition--
Operand stack: GS_PDF_ProcSet GS_PDF_ProcSet 971 971 918
918 865 865 812 812 760 760 707 707 654
...
Current file position is 24
A single equation on its own (same file, only one \begin{equation})
does not produce this crash, but also produces no visible image at
all -- see "Secondary issue" below.
=====================================================================
FIRST CONFIRMED BUG (fixed, patch included below)
=====================================================================
preview-gs-dsc-cvx (preview.el) generates PostScript for extracting
one page from the combined preview file, and its template already
begins with "dup":
(defun preview-gs-dsc-cvx (page dsc)
...
(format "dup %d setfileposition %d()/SubFileDecode filter cvx"
(1- (car curpage)) (nth 1 curpage)))
But its caller, preview-gs-transact, prepends *another* literal "dup "
on top of that when assembling the PostScript line for every queued
snippet after the first:
(gs-line
(format
"%s<<%s>>preview-do\n"
(if preview-ps-file
(concat "dup " ; <-- redundant
(preview-gs-dsc-cvx snippet preview-gs-dsc))
...)
...))
This produces "dup dup <pos> setfileposition ..." for every page after
the first, leaving one extra stray file-object reference on
Ghostscript's operand stack per additional queued snippet.
PATCH (tested locally, reduces but does not eliminate the crash --
see "Remaining issue" below):
--- a/preview.el
+++ b/preview.el
@@ -1524,10 +1524,9 @@
(gs-line
(format
"%s<<%s>>preview-do\n"
(if preview-ps-file
- (concat "dup "
- (preview-gs-dsc-cvx
- snippet
- preview-gs-dsc))
+ (preview-gs-dsc-cvx
+ snippet
+ preview-gs-dsc)
(format "%s(r)file cvx"
(preview-ps-quote-filename
VERIFICATION: comparing the Ghostscript error's PostScript-input trace
and operand stack before/after this change on the identical 8-equation
repro file:
BEFORE (unpatched):
...dup dup 654 setfileposition...
Operand stack: ... 971 971 971 918 918 918 865 865 865 ...
(each position triplicated)
AFTER (patched):
...dup 654 setfileposition...
Operand stack: ... 971 971 918 918 865 865 ...
(each position only duplicated, not triplicated)
The fix measurably removes exactly one stray copy per page, confirming
the redundant "dup " is real. However, the crash still occurs
afterward with the reduced (paired) stack -- so this is not the sole
cause.
=====================================================================
REMAINING ISSUE (not fixed, needs maintainer input)
=====================================================================
After applying the fix above, I wrote a standalone, Emacs-independent
PostScript test reproducing the exact preview-do / .preview-ST
choreography with trivial dummy per-page content (`(pageN ran)==`)
instead of real preview data, run directly through the same gs
10.02.1 binary. Across 3 repeated preview-do calls with the corrected
single-dup pattern, the operand stack returns to a clean, single-item
state after every call -- no leak at all.
This means the *mechanism* I identified and patched is not, by itself,
leaky when used correctly. Something about the *actual* per-page
content is contributing an additional stray stack item per page that
my synthetic content didn't reproduce.
I recovered the real (crashed) preview.dsc from a live session and
its relevant excerpt is:
%%BeginSetup
(_region_.pdf) (r) file { DELAYSAFER { .setsafe } if } stopped pop
runpdfbegin
process_trailer_attrs
%%EndSetup
%%Page: 1 1
1 DoPDFPage
%%Page: 2 2
2 DoPDFPage
...
/DoPDFPage {dup /Page# exch store dup dopdfpages } def
Unlike the classic dvips-generated multi-page PostScript that this
per-page splitting technique in preview.el was presumably designed
against, this is Ghostscript's own native PDF interpreter output
(runpdfbegin / dopdfpages are gs's built-in PDF-interpreter
operators, used here because the document compiles via pdflatex to
PDF, i.e. TeX-PDF-mode t). My working hypothesis, not yet confirmed,
is that dopdfpages (or the surrounding DoPDFPage wrapper) leaves a
residual item on the operand stack per invocation that the classic
splitting trick's bookkeeping (a save/restore pair per page, see
preview-do's definition) does not fully account for when the
per-page content is PDF-interpreter-driven rather than plain
dvips-style PostScript. I was not able to fully confirm this without
deeper knowledge of dopdfpages' internal contract.
=====================================================================
RULED OUT: preamble caching
=====================================================================
I initially suspected the "Cache preamble? " prompt
(preview-auto-cache-preamble) might gate whether multiple snippets get
batched into one shared compilation (and thus one multi-page PDF),
since that would explain why a single equation doesn't crash but a
batch does. Tested directly: answering both y and n to that prompt on
the identical 8-equation file produces a byte-for-byte identical crash
and operand-stack trace. This is not the deciding factor; whatever
batches the 8 equations into one _region_.pdf happens regardless of
the preamble-caching choice (preview-start-pdf2dsc appears to always
set preview-ps-file, unlike preview-start-dvips's `fast`-gated
version).
=====================================================================
SECONDARY ISSUE: single snippet produces no image at all
=====================================================================
With `preview-pdf-color-adjust-method` set to 'compatible, previewing
a *single* equation (no batching) does not crash, but also produces no
visible image -- the LaTeX source is left untouched with no error
surfaced. On a later attempt (same session, after having triggered the
batch crash above), the same single-equation file instead produced a
different error:
Error: /undefined in GS_PDF_ProcSet
...
Last OS error: No such file or directory
Current file position is 805
This looks like it could be a sandboxed-file-access (`.locksafe` /
PermitFileReading allowlist, visible in the same script) failing to
find the region PDF at the expected path, though I was not able to
fully isolate this from the batch-crash's possible lingering effects
on the persistent Ghostscript process AUCTeX reuses across preview
requests (preview-gs-queue / preview-gs-outstanding). Flagging this as
a second, distinct, less-understood data point rather than a confirmed
separate bug.
=====================================================================
RELATED OBSERVATION: preview-pdf-color-adjust-method default (t)
=====================================================================
Before trying 'compatible, the default value (t) produced previews
that render without crashing, but are effectively invisible: with a
non-default (dark) Emacs theme, small inline math snippets rendered
with borderline-legible contrast, while a larger, multi-line displayed
equation rendered as an apparently blank/near-invisible box (dark
text on a matching dark background). This inconsistency (some
snippets legible, others not, with no crash either way) suggests the
DELAYBIND-based color-adjustment path is not reliably computing
correct colors on this Ghostscript version, independent of the
setfileposition crash discussed above. Falling back to
preview-pdf-color-adjust-method = nil (plain black-on-white,
regardless of Emacs theme) works reliably with no crashes and
uniformly legible (if unstyled) output, and is what I am using as a
practical workaround while this is investigated.
=====================================================================
ATTACHMENTS AVAILABLE ON REQUEST
=====================================================================
- Full crashed preview.dsc (real file recovered from a live crashed
session, ~1.1KB, DSC/PDF boilerplate only, no document content) --
happy to send on request, it was cleaned up by AUCTeX before I could
attach it here.
- Full Ghostscript error transcripts for: the original real-world
document (a physics paper, ~30 pages, many equations/figures), the
8-equation minimal repro, and the single-equation case (both error
variants)
Thanks for looking into this.
_______________________________________________
bug-auctex mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-auctex