Subject: bug#77389: 31.0.50; Restarting Emacs with (kill-emacs ... t) looses noninteractivity

From: Jens Schmidt <[email-masked]>
Date: Sun, 30 Mar 2025 19:20:58 +0200

[ Disclaimer:

  - This is one of my more exotic bug reports, so I won't argue
    (at least not much) if you close this as "won't fix".

  - In particular since an Emacs restart, added by Lars in
    5be9a9ca, probably has only been meant to be used
    interactively.

  - But I do have a valid use case for a non-interactive restart,
    so I created this bug report ... ]

Write the following to a file named test.el:

------------------------- test.el -------------------------
(message "%S:%S" noninteractive command-line-args)
(when noninteractive
  (kill-emacs 0 t))
------------------------- test.el -------------------------

Then execute that file with

  ./src/emacs -Q --script test.el

I would expect that to inf-loop through the execvp from Fkill_emacs, but
instead it prints

  t:("./src/emacs" "-scriptload" "test.el")

to STDOUT and opens a GUI window with the message

  nil:("/home/jschmidt/work/emacs-master/src/emacs" "-scriptload" "test.el")

in its mode line.

Here is what I think happens (or at least a simplified version of
it, which does not cover e.g. the sorting of command line
arguments done by main):

1. The main function in emacs.c converts option "--script" to
   "-scriptload", setting the noninteractive flag while doing do:

     if (argmatch (argv, argc, "-script", "--script", 3, &junk, &skip_args))
       {
         noninteractive = 1;	/* Set batch mode.  */
         /* Convert --script to -scriptload, un-skip it, and sort again
            so that it will be handled in proper sequence.  */
         /* FIXME broken for --script=FILE - is that supposed to work?  */
         argv[skip_args - 1] = (char *) "-scriptload";
         skip_args -= 2;
         sort_args (argc, argv);
       }

2. Later in main, function init_cmdargs stores away the modified argv
   containing "-scriptload" into initial_argv.

3. When Fkill_emacs gets called with non-nil second argument, it calls
   function execvp on initial_argv, which contains "-scriptload" instead
   of "--script".

4. Therefore the next Emacs execution does not process the snippet
   quoted under 1. above and, hence, does not set the noninteractive
   flag.

As a work-around, one can put a "--batch" option before the "--script"
option, then above repro inf-loops as expected (by me).

Probably Fkill_emacs should call execvp not on the command line
arguments in initial_argv, which already got modified by main,
but on a copy of the *real* initial command line arguments as
they have been passed into main?  I have a patch to that effect,
and it also lets above repro inf-loop as expected by me.

Thanks as always for caring about exotic and non-exotic bugs and
Emacs as a whole!

In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.24.38, cairo version 1.16.0) of 2025-03-30 built on sappc2
Repository revision: a72cfc52cc36b8233969dafb202915d36c4c5a9e
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12201009
System Description: Debian GNU/Linux 12 (bookworm)

Configured using:
 'configure --with-native-compilation --with-mailutils'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NATIVE_COMP
NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND THREADS TIFF
TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINERAMA XINPUT2 XPM XRANDR GTK3
ZLIB

Important settings:
  value of $LC_COLLATE: POSIX
  value of $LC_TIME: POSIX
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  minibuffer-regexp-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr compile comint ansi-osc ansi-color ring comp-run
bytecomp byte-compile comp-common rx emacsbug lisp-mnt message mailcap
yank-media puny dired dired-loaddefs rfc822 mml mml-sec password-cache
epa derived epg rfc6068 epg-config gnus-util text-property-search
time-date subr-x mm-decode mm-bodies mm-encode mail-parse rfc2231
mailabbrev gmm-utils mailheader cl-loaddefs cl-lib sendmail rfc2047
rfc2045 ietf-drums mm-util mail-prsvr mail-utils rmc iso-transl tooltip
cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type
elisp-mode mwheel term/x-win x-win term/common-win x-dnd touch-screen
tool-bar dnd fontset image regexp-opt fringe tabulated-list replace
newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar
rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock
font-lock syntax font-core term/tty-colors frame minibuffer nadvice seq
simple cl-generic indonesian philippine cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese composite emoji-zwj charscript charprop case-table
epa-hook jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button
loaddefs theme-loaddefs faces cus-face macroexp files window
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget keymap hashtable-print-readable backquote threads dbusbind
inotify lcms2 dynamic-setting system-font-setting font-render-setting
cairo gtk x-toolkit xinput2 x multi-tty move-toolbar
make-network-process tty-child-frames native-compile emacs)

Memory information:
((conses 16 57068 9506) (symbols 48 6816 0) (strings 32 16707 3815)
 (string-bytes 1 439863) (vectors 16 11584)
 (vector-slots 8 134675 5392) (floats 8 21 14) (intervals 56 249 0)
 (buffers 984 11))