Subject: bug#58752: closed (Re: bug#58752: jit-lock-function infinite loop?)

From: [email-masked] (GNU bug Tracking System)
Date: Thu, 27 Oct 2022 16:19:03 +0000

Your bug report

#58752: jit-lock-function infinite loop?

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
58752: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=58752
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#58752: jit-lock-function infinite loop?
From: Eli Zaretskii <[email-masked]>
To: Alex Holehouse <[email-masked]>
Cc: [email-masked]
Date: Thu, 27 Oct 2022 19:17:47 +0300
List-Id: <debbugs-submit.debbugs.gnu.org>

> From: Alex Holehouse <[email-masked]>
> Date: Sun, 23 Oct 2022 18:37:37 -0500
> 
> Apologies if this is a reported and known issue, but after several hours of tracking this down, I think I've found
> a bug in the font-lock module when working with Python code on Emacs28 (macOS 12.6 on Apple Silicon
> (M1)). This is an issue certainly in Emacs 28 but not in earlier versions, so my temporary fix here is just to
> revert back to emacs 26; I haven't tested 27.
> 
> I think the issue stems from inside the jit-lock-function in font-lock.el, although my experience in hunting down
> emacs issues is limited. 
> 
> Specifically, it seems that the function falls into an infinite loop when trying to format ill-behaving Python code.
> The issue arises when a specific combination of things are true: an un-closed docstring that opens with three
> double quotes (but does not close) followed by docstrings in other functions with 4 or more examples of single
> quotation marks that are unsatisfied. These unsatisfied single quotation marks are, of course, allowed inside a
> docstring, which means even when editing a Python file, if the unclosed triple double-quote docstring appears
> event temporarily (e.g. as you're writing the docstring) the entire program freezes. 
> 
> I've narrowed this down to a minimal example that, at least in my setup (nothing fancy, vanilla emacs from
> both emacsformacosx and from homebrew), reproduces the issue. The code snippet can be found here:
> https://gist.github.com/alexholehouse/2259580ed2cb2caf75a16ee31d927465 
> 
> If you open this file in emacs, the code renders but if you scroll down emacs freezes, but can be unfrozen by
> running kill -SIGUSR2 <emacs PID> from another terminal window.

Thank you very much for your efforts to provide a minimal example.

I can reproduce this bug in Emacs 28, but not in Emacs 29.  So I think
the underlying bug was already fixed, and I'm therefore closing this
bug.

Subject: jit-lock-function infinite loop?
From: Alex Holehouse <[email-masked]>
To: [email-masked]
Date: Sun, 23 Oct 2022 18:37:37 -0500
List-Id: <debbugs-submit.debbugs.gnu.org>

Dear all,

Apologies if this is a reported and known issue, but after several hours of
tracking this down, I think I've found a bug in the font-lock module when
working with Python code on Emacs28 (macOS 12.6 on Apple Silicon (M1)).
This is an issue certainly in Emacs 28 but not in earlier versions, so my
temporary fix here is just to revert back to emacs 26; I haven't tested 27.

I think the issue stems from inside the jit-lock-function in font-lock.el,
although my experience in hunting down emacs issues is limited.

Specifically, it seems that the function falls into an infinite loop when
trying to format ill-behaving Python code. The issue arises when a specific
combination of things are true: an un-closed docstring that opens with
three double quotes (but does not close) followed by docstrings in other
functions with 4 or more examples of single quotation marks that are
unsatisfied. These unsatisfied single quotation marks are, of course,
allowed inside a docstring, which means even when editing a Python file, if
the unclosed triple double-quote docstring appears event temporarily (e.g.
as you're writing the docstring) the entire program freezes.

I've narrowed this down to a minimal example that, at least in my setup
(nothing fancy, vanilla emacs from both emacsformacosx and from homebrew),
reproduces the issue. The code snippet can be found here:
https://gist.github.com/alexholehouse/2259580ed2cb2caf75a16ee31d927465

If you open this file in emacs, the code renders but if you scroll down
emacs freezes, but can be unfrozen by running kill -SIGUSR2 <emacs PID>
from another terminal window.

It's possible an even simpler minimal demonstrating case exists, but it
took me many hours to get to this!

Additional bug-reporting stuff is included below. I've not been able to
test this on a linuxbox yet, but have tested on a couple of different
machines running macOS all showing the same result.

I'm happy to follow up with this if I can be of help. Additional technical
info below, but, minimally the Gist linked above should make this
reproducible.

In GNU Emacs 28.2 (build 1, aarch64-apple-darwin21.1.0, NS appkit-2113.00
Version 12.0.1 (Build 21A559))
 of 2022-09-12 built on armbob.lan
Windowing system distributor 'Apple', version 10.3.2113
System Description:  macOS 12.6

Configured using:
 'configure --with-ns '--enable-locallisppath=/Library/Application
 Support/Emacs/${version}/site-lisp:/Library/Application
 Support/Emacs/site-lisp' --with-modules'

Configured features:
ACL GMP GNUTLS JSON LIBXML2 MODULES NOTIFY KQUEUE NS PDUMPER THREADS
TOOLKIT_SCROLL_BARS ZLIB

Important settings:
  value of $LC_CTYPE: en_US.UTF-8
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Debugger

Minor modes in effect:
  global-auto-complete-mode: t
  shell-dirtrack-mode: t
  tooltip-mode: t
  global-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
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  buffer-read-only: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t

Load-path shadows:
/Users/alex/.emacs.d/elpa/org-20140728/ob-exp hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-exp
/Users/alex/.emacs.d/elpa/org-20140728/ob-emacs-lisp hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-emacs-lisp
/Users/alex/.emacs.d/elpa/org-20140728/ob-css hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-css
/Users/alex/.emacs.d/elpa/org-20140728/ob-lob hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-lob
/Users/alex/.emacs.d/elpa/org-20140728/org-macs hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-macs
/Users/alex/.emacs.d/elpa/org-20140728/ob hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob
/Users/alex/.emacs.d/elpa/org-20140728/org-version hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-version
/Users/alex/.emacs.d/elpa/org-20140728/ob-scheme hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-scheme
/Users/alex/.emacs.d/elpa/org-20140728/ox hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox
/Users/alex/.emacs.d/elpa/org-20140728/ob-C hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-C
/Users/alex/.emacs.d/elpa/org-20140728/org-capture hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-capture
/Users/alex/.emacs.d/elpa/org-20140728/ob-ref hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-ref
/Users/alex/.emacs.d/elpa/org-20140728/ob-clojure hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-clojure
/Users/alex/.emacs.d/elpa/org-20140728/org-mouse hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-mouse
/Users/alex/.emacs.d/elpa/org-20140728/org-ctags hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-ctags
/Users/alex/.emacs.d/elpa/org-20140728/org-entities hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-entities
/Users/alex/.emacs.d/elpa/org-20140728/org-archive hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-archive
/Users/alex/.emacs.d/elpa/org-20140728/ob-screen hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-screen
/Users/alex/.emacs.d/elpa/org-20140728/ob-haskell hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-haskell
/Users/alex/.emacs.d/elpa/org-20140728/org-table hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-table
/Users/alex/.emacs.d/elpa/org-20140728/ox-org hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-org
/Users/alex/.emacs.d/elpa/org-20140728/org-plot hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-plot
/Users/alex/.emacs.d/elpa/org-20140728/ob-awk hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-awk
/Users/alex/.emacs.d/elpa/org-20140728/ob-octave hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-octave
/Users/alex/.emacs.d/elpa/org-20140728/org-faces hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-faces
/Users/alex/.emacs.d/elpa/org-20140728/org-colview hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-colview
/Users/alex/.emacs.d/elpa/org-20140728/ob-R hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-R
/Users/alex/.emacs.d/elpa/org-20140728/org-timer hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-timer
/Users/alex/.emacs.d/elpa/org-20140728/org-mobile hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-mobile
/Users/alex/.emacs.d/elpa/org-20140728/ob-fortran hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-fortran
/Users/alex/.emacs.d/elpa/org-20140728/ob-perl hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-perl
/Users/alex/.emacs.d/elpa/org-20140728/ob-sqlite hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-sqlite
/Users/alex/.emacs.d/elpa/org-20140728/org-list hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-list
/Users/alex/.emacs.d/elpa/org-20140728/ob-ruby hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-ruby
/Users/alex/.emacs.d/elpa/org-20140728/ob-eval hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-eval
/Users/alex/.emacs.d/elpa/org-20140728/org-habit hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-habit
/Users/alex/.emacs.d/elpa/org-20140728/org-clock hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-clock
/Users/alex/.emacs.d/elpa/org-20140728/ox-html hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-html
/Users/alex/.emacs.d/elpa/org-20140728/org-src hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-src
/Users/alex/.emacs.d/elpa/org-20140728/ob-lisp hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-lisp
/Users/alex/.emacs.d/elpa/org-20140728/ob-ditaa hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-ditaa
/Users/alex/.emacs.d/elpa/org-20140728/org-pcomplete hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-pcomplete
/Users/alex/.emacs.d/elpa/org-20140728/ox-latex hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-latex
/Users/alex/.emacs.d/elpa/org-20140728/ob-sass hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-sass
/Users/alex/.emacs.d/elpa/org-20140728/ob-tangle hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-tangle
/Users/alex/.emacs.d/elpa/org-20140728/ob-calc hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-calc
/Users/alex/.emacs.d/elpa/org-20140728/ob-java hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-java
/Users/alex/.emacs.d/elpa/org-20140728/ox-icalendar hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-icalendar
/Users/alex/.emacs.d/elpa/org-20140728/ox-md hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-md
/Users/alex/.emacs.d/elpa/org-20140728/ox-beamer hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-beamer
/Users/alex/.emacs.d/elpa/org-20140728/org-element hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-element
/Users/alex/.emacs.d/elpa/org-20140728/org-protocol hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-protocol
/Users/alex/.emacs.d/elpa/org-20140728/ob-gnuplot hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-gnuplot
/Users/alex/.emacs.d/elpa/org-20140728/ob-latex hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-latex
/Users/alex/.emacs.d/elpa/org-20140728/org-id hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-id
/Users/alex/.emacs.d/elpa/org-20140728/ox-man hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-man
/Users/alex/.emacs.d/elpa/org-20140728/org-feed hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-feed
/Users/alex/.emacs.d/elpa/org-20140728/ob-table hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-table
/Users/alex/.emacs.d/elpa/org-20140728/ob-ocaml hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-ocaml
/Users/alex/.emacs.d/elpa/org-20140728/org-indent hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-indent
/Users/alex/.emacs.d/elpa/org-20140728/ob-lilypond hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-lilypond
/Users/alex/.emacs.d/elpa/org-20140728/ob-matlab hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-matlab
/Users/alex/.emacs.d/elpa/org-20140728/org-datetree hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-datetree
/Users/alex/.emacs.d/elpa/org-20140728/ob-python hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-python
/Users/alex/.emacs.d/elpa/org-20140728/ob-makefile hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-makefile
/Users/alex/.emacs.d/elpa/org-20140728/org-agenda hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-agenda
/Users/alex/.emacs.d/elpa/org-20140728/ob-dot hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-dot
/Users/alex/.emacs.d/elpa/org-20140728/ob-js hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-js
/Users/alex/.emacs.d/elpa/org-20140728/ox-publish hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-publish
/Users/alex/.emacs.d/elpa/org-20140728/org-inlinetask hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-inlinetask
/Users/alex/.emacs.d/elpa/org-20140728/ob-org hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-org
/Users/alex/.emacs.d/elpa/org-20140728/ob-core hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-core
/Users/alex/.emacs.d/elpa/org-20140728/org-compat hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-compat
/Users/alex/.emacs.d/elpa/org-20140728/ox-odt hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-odt
/Users/alex/.emacs.d/elpa/org-20140728/ob-plantuml hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-plantuml
/Users/alex/.emacs.d/elpa/org-20140728/ox-ascii hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-ascii
/Users/alex/.emacs.d/elpa/org-20140728/org-loaddefs hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-loaddefs
/Users/alex/.emacs.d/elpa/org-20140728/ob-maxima hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-maxima
/Users/alex/.emacs.d/elpa/org-20140728/org hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org
/Users/alex/.emacs.d/elpa/org-20140728/org-macro hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-macro
/Users/alex/.emacs.d/elpa/org-20140728/ob-sql hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-sql
/Users/alex/.emacs.d/elpa/org-20140728/org-attach hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-attach
/Users/alex/.emacs.d/elpa/org-20140728/ox-texinfo hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ox-texinfo
/Users/alex/.emacs.d/elpa/org-20140728/org-crypt hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-crypt
/Users/alex/.emacs.d/elpa/org-20140728/org-footnote hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-footnote
/Users/alex/.emacs.d/elpa/org-20140728/org-install hides
/Applications/Emacs.app/Contents/Resources/lisp/org/org-install
/Users/alex/.emacs.d/elpa/org-20140728/ob-comint hides
/Applications/Emacs.app/Contents/Resources/lisp/org/ob-comint

Features:
(shadow sort mail-extr emacsbug message rmc puny dired dired-loaddefs
rfc822 mml mml-sec epa epg rfc6068 epg-config gnus-util rmail
rmail-loaddefs mm-decode mm-bodies mm-encode mail-parse rfc2231
mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums
mm-util mail-prsvr mail-utils help-fns radix-tree cl-print debug
backtrace help-mode find-func advice flymake-proc flymake project
compile text-property-search warnings thingatpt auto-complete-config
auto-complete popup edmacro kmacro cython-mode derived rx python
tramp-sh tramp tramp-loaddefs trampver tramp-integration files-x
tramp-compat shell pcomplete parse-time iso8601 time-date ls-lisp
format-spec comint ring ansi-color manoj-dark-theme
auto-complete-autoloads color-theme-autoloads
color-theme-twilight-autoloads frame-cmds-autoloads frame-fns-autoloads
info org-autoloads popup-autoloads package browse-url url url-proxy
url-privacy url-expand url-methods url-history url-cookie url-domsuf
url-util mailcap url-handlers url-parse auth-source cl-seq eieio
eieio-core cl-macs eieio-loaddefs password-cache json subr-x map
url-vars seq byte-opt gv bytecomp byte-compile cconv cl-loaddefs cl-lib
iso-transl tooltip eldoc paren electric uniquify ediff-hook vc-hooks
lisp-float-type elisp-mode mwheel term/ns-win ns-win ucs-normalize
mule-util term/common-win 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 cl-generic 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 simple abbrev obarray cl-preloaded nadvice button
loaddefs faces cus-face macroexp files window text-properties overlay
sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote threads kqueue cocoa ns multi-tty
make-network-process emacs)

Memory information:
((conses 16 116139 7835)
 (symbols 48 12579 1)
 (strings 32 43554 931)
 (string-bytes 1 1351630)
 (vectors 16 25779)
 (vector-slots 8 349319 13383)
 (floats 8 89 206)
 (intervals 56 519 0)
 (buffers 992 14))

------------------------------------------------------------
Debugger information after using kill -SIGUSR2 to interrupt the infinite
loop

Debugger entered--entering a function:
* #f(compiled-function () #<bytecode 0x8811dd20548771a>)()
  syntax-ppss()
  python-nav-end-of-statement()
  python-nav-end-of-block()
  python-info-statement-ends-block-p()
  python-nav--forward-sexp(-1 nil nil)
  python-nav-forward-sexp(-1 nil nil)
  python-nav-backward-sexp()
  python-info-docstring-p((0 nil nil 34 nil nil 0 nil 2153 nil nil))
  python-font-lock-syntactic-face-function((0 nil nil 34 nil nil 0 nil 2153
nil nil))
  font-lock-fontify-syntactically-region(1587 2258 nil)
  font-lock-default-fontify-region(1587 2258 nil)
  font-lock-fontify-region(1587 2258)
  #f(compiled-function (fun) #<bytecode
0x19d0fed4ca014bfd>)(font-lock-fontify-region)
  run-hook-wrapped(#f(compiled-function (fun) #<bytecode
0x19d0fed4ca014bfd>) font-lock-fontify-region)
  jit-lock--run-functions(1587 2258)
  jit-lock-fontify-now(1587 3087)
  jit-lock-function(1587)
  redisplay_internal\ \(C\ function\)()

------------------------------------------------------------

Much appreciated,

~ alex