From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Adam Van Ymeren Newsgroups: gmane.emacs.bugs Subject: bug#40907: Font-lock-mode hanging in Java buffers Date: Mon, 27 Apr 2020 18:21:09 +0000 Message-ID: References: <215d8224-219b-ad06-ba4a-f99250e0a56d@yandex.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="40256"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 To: Dmitry Gutov , 40907@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Apr 27 20:29:40 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jT8Vf-000AJW-GE for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 27 Apr 2020 20:29:39 +0200 Original-Received: from localhost ([::1]:58276 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jT8Ve-0005DZ-Gt for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 27 Apr 2020 14:29:38 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:35544) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jT8OL-00009b-2Q for bug-gnu-emacs@gnu.org; Mon, 27 Apr 2020 14:22:05 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.90_1) (envelope-from ) id 1jT8OI-0002nN-Pq for bug-gnu-emacs@gnu.org; Mon, 27 Apr 2020 14:22:04 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:54767) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jT8OI-0002nB-Cg for bug-gnu-emacs@gnu.org; Mon, 27 Apr 2020 14:22:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1jT8OI-0004Wx-8w for bug-gnu-emacs@gnu.org; Mon, 27 Apr 2020 14:22:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Adam Van Ymeren Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 27 Apr 2020 18:22:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 40907 X-GNU-PR-Package: emacs Original-Received: via spool by 40907-submit@debbugs.gnu.org id=B40907.158801167417353 (code B ref 40907); Mon, 27 Apr 2020 18:22:02 +0000 Original-Received: (at 40907) by debbugs.gnu.org; 27 Apr 2020 18:21:14 +0000 Original-Received: from localhost ([127.0.0.1]:38080 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jT8NV-0004Vo-Pr for submit@debbugs.gnu.org; Mon, 27 Apr 2020 14:21:14 -0400 Original-Received: from mail2.vany.ca ([142.54.190.254]:34260) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jT8NT-0004Ve-FY for 40907@debbugs.gnu.org; Mon, 27 Apr 2020 14:21:12 -0400 Original-Received: from [192.168.1.2] (unknown [192.159.180.39]) by mail2.vany.ca (Postfix) with ESMTPSA id 1D32AAC016D; Mon, 27 Apr 2020 13:21:10 -0500 (CDT) In-Reply-To: <215d8224-219b-ad06-ba4a-f99250e0a56d@yandex.ru> Content-Language: en-US X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:179170 Archived-At: On 2020-04-27 5:38 p.m., Dmitry Gutov wrote: > On 27.04.2020 20:30, Adam Van Ymeren wrote: >> I've been doing a lot of Java work lately, and I'm having issues with >> emacs hanging and spinning at 100% CPU.  I believe the culprit to be >> font-lock-mode.  C-g doesn't save me either, I usually have to kill >> emacs.  Any advice on how to debug this if C-g doesn't work? > > You can send the USR2 signal to the Emacs process to try to interrupt > what it's doing and enter the debugger: > > kill -SIGUSR2 > > To fix this, we'll most likely need the contents of the buffer that > has the problem. If it's proprietary, you could try recreating the > problem from scratch, or replacing all identifiers in the code with > something else, etc. > > You could also try a build of Emacs 27 first before doing all that. Wow SIGUSR2 is magical, thanks for that tip.  I reproduced it once visiting a particular file but it's not happening reliably for me now.  Below is the stacktrace and the contents of the associated buffer, but it's not reproducing reliably.  Now that I know about SIGUSR2 I'll report back with a reliable repro once I figure one out. Here's the emacs stacktrace: Debugger entered--entering a function: * #f(compiled-function () #)()   c-parse-state()   c-syntactic-skip-backward("^;{}" 5344 t)   c-fl-decl-start(5927)   c-context-expand-fl-region(5927 6427)   #f(compiled-function (fn) #)(c-context-expand-fl-region)   mapc(#f(compiled-function (fn) #) (c-context-expand-fl-region))   c-before-context-fl-expand-region(5927 6427)   c-font-lock-fontify-region(5927 6427 nil)   font-lock-fontify-region(5927 6427)   #f(compiled-function (fun) #)(font-lock-fontify-region)   run-hook-wrapped(#f(compiled-function (fun) #) font-lock-fontify-region)   jit-lock--run-functions(5927 6427)   jit-lock-fontify-now(5927 6427)   jit-lock-function(5927)   redisplay_internal\ \(C\ function\)() And the buffer contents are given after ==== =============== /**  * @license  * Copyright 2017 The FOAM Authors. All Rights Reserved.  * http://www.apache.org/licenses/LICENSE-2.0  */ package foam.dao; import foam.core.*; import foam.dao.index.*; import foam.mlang.order.Comparator; import foam.mlang.predicate.Or; import foam.mlang.predicate.Predicate; import foam.mlang.sink.GroupBy; import foam.nanos.logger.Logger; import foam.nanos.pm.PM; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; /**  The MDAO class for an ordering, fast lookup, single value,  index multiplexer, or any other MDAO select() assistance class.  The assitance class TreeIndex implements the  data nodes that hold the indexed items and plan and execute  queries. For any particular operational Index, there may be  many IndexNode instances:  

  1---------> TreeIndex(id)

  MDAO: AltIndex 2---------> TreeIndex(propA) ---> TreeIndex(id) -------------> ValueIndex

  | 1x AltIndexNode    | 1x TreeIndexNode    | 14x TreeIndexNodes         | (DAO size)x ValueIndexNodes

  (2 alt subindexes)     (14 nodes)             (each has 0-5 nodes)

  
 The base AltIndex has two complete subindexes (each holds the entire DAO).  The TreeIndex on property A has created one TreeIndexNode, holding one tree of 14 nodes.  Each tree node contains a tail instance of the next level down, thus  the TreeIndex on id has created 14 TreeIndexNodes. Each of those contains some number  of tree nodes, each holding one tail instance of the ValueIndex at the end of the chain.  */  // TODO: clone and freeze objects stored in memory public class MDAO   extends AbstractDAO {   protected AltIndex index_;   protected Object   state_ = null;   protected Object   writeLock_ = new Object();   protected Set      unindexed_ = new HashSet();   public MDAO(ClassInfo of) {     setOf(of);     index_ = new AltIndex(new TreeIndex((PropertyInfo) this.of_.getAxiomByName("id")));   }   public void addIndex(Index index) {     synchronized ( writeLock_ ) {       state_ = index_.addIndex(state_, index);     }   }   /** Add an Index which is for a unique value. Use addIndex() if the index is not unique. **/   public void addUniqueIndex(PropertyInfo... props) {     Index i = ValueIndex.instance();     for ( PropertyInfo prop : props ) i = new TreeIndex(prop, i);     addIndex(i);   }   /** Add an Index which is for a non-unique value. The 'id' property is    * appended to property list to make it unique.    **/   public void addIndex(PropertyInfo... props) {     Index i = new TreeIndex((PropertyInfo) this.of_.getAxiomByName("id"));     for ( PropertyInfo prop : props ) i = new TreeIndex(prop, i);     addIndex(i);   }   synchronized Object getState() {     return state_;   }   synchronized void setState(Object state) {     state_ = state;   }   public FObject objIn(FObject obj) {     return obj.fclone().freeze();   }   public FObject objOut(FObject obj) {     return obj;   }   public FObject put_(X x, FObject obj) {     // Clone and freeze outside of lock to minimize time spent under lock     obj = objIn(obj);     synchronized ( writeLock_ ) {       FObject oldValue = find_(x, obj);       Object  state    = getState();       if ( oldValue != null ) {         state = index_.remove(state, oldValue);       }       setState(index_.put(state, obj));     }     onPut(obj);     return obj;   }   public FObject remove_(X x, FObject obj) {     if ( obj == null ) return null;     FObject found;     synchronized ( writeLock_ ) {       found = find_(x, obj);       if ( found != null ) {         setState(index_.remove(getState(), found));       }     }     if ( found != null ) {       onRemove(found);     }     return found;   }   public FObject find_(X x, Object o) {     Object state;     state = getState();     if ( o == null ) return null;     // TODO: PM unindexed plans     return objOut(       getOf().isInstance(o)         ? (FObject) index_.planFind(state, getPrimaryKey().get(o)).find(state, getPrimaryKey().get(o))         : (FObject) index_.planFind(state, o).find(state, o)     );   }   public Sink select_(X x, Sink sink, long skip, long limit, Comparator order, Predicate predicate) {     Logger     logger = (Logger) x.get("logger");     SelectPlan plan;     Predicate  simplePredicate = null;     PM         pm = null;     // use partialEval to wipe out such useless predicate such as: And(EQ()) ==> EQ(), And(And(EQ()),GT()) ==> And(EQ(),GT())     if ( predicate != null ) simplePredicate = predicate.partialEval();     Object state = getState();     // We handle OR logic by seperate request from MDAO. We return different plan for each parameter of OR logic.     if ( simplePredicate instanceof Or ) {       Sink dependSink = new ArraySink();       // When we have groupBy, order, skip, limit such requirement, we can't do it separately so I replace a array sink to temporarily holde the whole data       //Then after the plan wa slelect we change it to the origin sink       int length = ((Or) simplePredicate).getArgs().length;       List planList = new ArrayList<>();       for ( int i = 0 ; i < length ; i++ ) {         Predicate arg = ((Or) simplePredicate).getArgs()[i];         planList.add(index_.planSelect(state, dependSink, 0, AbstractDAO.MAX_SAFE_INTEGER, null, arg));       }       plan = new OrPlan(simplePredicate, planList);     } else {       plan = index_.planSelect(state, sink, skip, limit, order, simplePredicate);     }     if ( state != null && predicate != null && plan.cost() > 10 && plan.cost() >= index_.size(state) ) {       pm = new PM(this.getClass(), "MDAO:UnindexedSelect:" + getOf().getId());       if ( ! unindexed_.contains(getOf().getId())) {         if ( ! predicate.equals(simplePredicate) &&              logger != null ) {             logger.debug(String.format("The original predicate was %s but it was simplified to %s.", predicate.toString(), simplePredicate.toString()));         }         unindexed_.add(getOf().getId());         if ( logger != null ) {           logger.warning("Unindexed search on MDAO", getOf().getId(), simplePredicate.toString());         }       }     }     plan.select(state, sink, skip, limit, order, simplePredicate);     if ( pm != null ) pm.log(x);     sink.eof();     return sink;   }   public void removeAll_(X x, long skip, long limit, Comparator order, Predicate predicate) {     if ( predicate == null && skip == 0 && limit == MAX_SAFE_INTEGER ) {       synchronized ( writeLock_ ) {         setState(null);       }     } else {       super.removeAll_(x, skip, limit, order, predicate);     }   } }