Subject: bug#78898: Make read/readevalloop reentrant

From: Pip Cet <[email-masked]>
Date: Fri, 27 Jun 2025 09:41:58 +0000

"Lynn Winebarger" <[email-masked]> writes:

Thanks for providing an updated patch!  It applies and, with the changes
below, it seems to work for me.

I haven't really looked at the code yet, just tried to get it to work.
I did notice that, at least with debug CFLAGS, Emacs startup is much
slower than it was before.

Is there any possibility of splitting this into several smaller patches?
I get the impression it would be a lot of work, but maybe I'm wrong.

> I tried explicitly forcing emacs-internal as the coding-system for
> load_source_file, but without any noticeable difference.

Hmm.  I think the problem there is that you specbind
Qcoding_system_for_read to Qemacs_internal while calling
dump-emacs-portable.  The pdumper doesn't unwind specbind bindings, so
the Vcoding_system_for_read variable is dumped with that value, and
restored with that value from the dump, and then things go wrong because
other code assumes Vcoding_system_for_read is nil.

> The button preceding the warning messages should be a stop sign emoji.
> Using the built emacs to view emacs-lisp/warning.el shows the stop
> sign emoji clearly, but it is apparently mangled in the generated
> byte-code in warning.elc.

To me, it looks like it's encoded in warnings.elc as a UTF-8 sequence.
But you force coding_system_for_read to emacs-internal, so it's read as
garbage.  The same problem, by the way, applies to ja-dic-cnv.el, which
contains verbatim UTF-8 data which is then copied into ja-dic-cnv.elc
and misread, which causes the wrong-type-argument you've described.

Here's a non-fix:

diff --git a/lisp/emacs-lisp/warnings.el b/lisp/emacs-lisp/warnings.el
index 6c77d57a6ba..ae02bc2a94b 100644
--- a/lisp/emacs-lisp/warnings.el
+++ b/lisp/emacs-lisp/warnings.el
@@ -1,4 +1,4 @@
-;;; warnings.el --- log and display warnings  -*- lexical-binding:t -*-
+;;; warnings.el --- log and display warnings  -*- lexical-binding:t; no-byte-compile: t -*-
 
 ;; Copyright (C) 2002-2025 Free Software Foundation, Inc.
 
diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el
index 901d1742af5..2c76291a8f3 100644
--- a/lisp/international/ja-dic-cnv.el
+++ b/lisp/international/ja-dic-cnv.el
@@ -1,4 +1,4 @@
-;;; ja-dic-cnv.el --- convert a Japanese dictionary (SKK-JISYO.L) to Emacs Lisp  -*- lexical-binding: t; -*-
+;;; ja-dic-cnv.el --- convert a Japanese dictionary (SKK-JISYO.L) to Emacs Lisp  -*- lexical-binding: t; no-byte-compile: t -*-
 
 ;; Copyright (C) 2001-2025 Free Software Foundation, Inc.

And these two look like necessary fixes to me:

diff --git a/src/lread.c b/src/lread.c
index cb8559f455c..6dd06614270 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1217,7 +1217,7 @@ #define READCHAR_BEGIN(frame) \
   while (0)
 
 #define READCHAR_FROM_FILE_BEGIN(frame) \
-  unsigned char buf[4]; \
+  unsigned char buf[MAX_MULTIBYTE_LENGTH]; \
   READCHAR_BEGIN(frame); \
   c = readbyte_from_file (frame); \
   if (c < 0) \
diff --git a/src/pdumper.c b/src/pdumper.c
index b3de90bfa03..536716bdba0 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -4243,6 +4243,7 @@ DEFUN ("dump-emacs-portable",
   ctx->old_process_environment = Vprocess_environment;
   Vprocess_environment = Qnil;
 
+  Vcoding_system_for_read = Qnil;
   {
     USE_SAFE_ALLOCA;

With this patch, I can build Emacs and launch it.

The rest of the email is about the specific differences you mentioned.

> I also built a clean emacs from commit
> 2bdcf0250acecdb0719203ae711aedf5baad1783.  When I compared the source
> elisp files (after building) I see differences in these files:
> lisp/international/uni-bidi.el
> lisp/international/uni-brackets.el
> lisp/international/uni-category.el
> lisp/international/uni-combining.el
> lisp/international/uni-comment.el
> lisp/international/uni-decomposition.el
> lisp/international/uni-old-name.el
> lisp/international/uni-name.el

On my system, these files include the path to the emacs directory, so
the differences would make sense unless you built both trees in the same
directory.

> lisp/leim/leim-list.el
> lisp/leim/ja-dic/ja-dic.el

No differences here, after the patch.

> lisp/net/tramp-loaddefs.el

Or here; as tramp makes heavy use of defsubst, in parallel builds, there
will often be differences in the bytecode/generated files produced for
tramp.

> lisp/textmodes/reftex-loaddefs.el
> lisp/finder-inf.el

No differences here.

> lisp/loaddefs.el
> lisp/cus-load.el

Differences here, but they look harmless.

> In the byte-compiled files, I see differences for:
> lisp/emacs-lisp/eieio-opt.elc
> lisp/erc/erc-nicks.elc
> lisp/erc/erc.elc
> lisp/eshell/em-cmpl.elc
> lisp/gnus/gnus-group.elc
> lisp/gnus/gnus-srvr.elc
> lisp/gnus/gnus-topic.elc
> lisp/gnus/gnus-sieve.elc
> lisp/gnus/gnus-search.elc
> lisp/gnus/message.elc
> lisp/gnus/nnfeed.elc
> lisp/gnus/nnml.elc
> lisp/gnus/nnimap.elc
> lisp/gnus/nnagent.elc
> lisp/gnus/nnmaildir.elc
> lisp/gnus/gnus-start.elc
> lisp/gnus/gnus-sum.elc
> lisp/gnus/nnmairix.elc
> lisp/gnus/nnselect.elc
> lisp/net/tramp-cache.elc
> lisp/net/tramp-cmds.elc
> lisp/net/tramp-gvfs.elc
> lisp/net/tramp-sh.elc
> lisp/obsolete/nnir.elc
> lisp/org/org-agenda.elc
> lisp/org/org-lint.elc
> lisp/org/ox-ascii.elc
> lisp/org/ox-odt.elc
> lisp/org/org.elc
> lisp/progmodes/eglot.elc
> lisp/progmodes/cc-engine.elc
> lisp/progmodes/cc-mode.elc
> lisp/progmodes/js.elc
> lisp/use-package/use-package-core.elc
> lisp/loaddefs.elc

I haven't looked over all these files.  Some of them include the source
path, but see below for eieio-opt.elc.

> I'm not clear on why loaddefs.el should be different.  That, and
> eieio-opt.elc being different is unexpected.

Did you use a parallel build?  As our defsubst expansion is
unpredictable in parallel builds, there may be bytecode differences that
will simply go away if you rebuild (bootstrap) without the "-j" flag.  I
suspect that's what happened here, since I don't see a difference in
that file.

It might be worth it to build both trees in the same file system
directory, and to use a non-parallel make, then run diff -aur a/lisp
b/lisp to look for actual differences.  (I'd suggest disabling native
compilation for now if that takes too long).

Pip