🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.bug
Article #99856

Bug(?) GNU-emacs

#99856
From: CI
Date: Sun, 22 Apr 1990 10:44
188 lines
7022 bytes
	
Hello. 
(I am sending this to uunet!mit-eddie!bug-gnu-emacs, if there is a
better mail address, please let me know. I am still unfamiliar with
e-mail addresses.)

I have updated my file to 18.55 and I would like to report one
possible bug of GNU-emacs.
This is concerning the possible recursive blow up of memory allocator
and error message routine when it runs out of memory.

PROBLEM: When GNU-Emacs runs out of memory, it may blow up when
the error handling functions are called recursively.

CAUSE: When the memory allocator (or realloc) is called,
it may find that the memory is exhausted.
memory_full() routine in alloc.c may be called in order to
output an error message.
In memory_full(), the call to error("Memory exhausted") is done.
The problem is that error(), IN TURN, calls Fcons and build_string()
in itself.
	cf.
	...
	  while (1)
	    Fsignal (Qerror, Fcons (build_string (buf), Qnil));

Depending on the exact moment when this error condition occurs
either Fcons or build_string can call malloc()!

	Fcons: when cons_block is exhausted at the moment, it will try to call
	      malloc() which WILL RESULT IN another memory_full()
	      call, thus recursively blow up the program!
	build_string(): this can also call malloc() if
		current_string_block is already exhausted, and again this will
		lead to recursive blow up.

REPEAT-BY: Very difficult to observe because you need to
be at the right moment when current_string_block and
cons_block are exhausted, but I could reproduce it
a few times when I tried to clean up etc/DOC-nn... file using
Emacs-lisp functions to produce a handly listing of emacs-lisp functions.
I checked the stack trace to confirm my above observation, and it took time...

MY FIX: Very simple. I create the error message data
structure in advance so that memory_full() will not try to call
malloc() when memory is running out.
Two files are rewritten. alloc.c and emacs.c

FILE alloc.c:
...
memory_full ()
{
#ifndef MFULLBUG
  error ("Memory exhausted");    /* <--- This is original code. */
#else
/* CI Believe it or not, Fcons and Fsignal inside error() caused additional
   errors which called this routine and eventually resulted in
   (recursive) stack overflow!
   (This is due to the fact that error() called more Fcons and build_string.)
   I think the best way is to store in advance the data of
   Fcons (build_string("Memory Exhausted"), Qnil), which is called in error(),
   in a  pure storage and use the value of data as the 2nd argument 
   Fsignal below. 
   So the steps to take will be;
      define lisp symbol and let it be known to
     lisp system by something like the following.
   The best place to do the above will be around the init time, but
   be careful since Qnil and Qt may not have been defined yet then.
   I decided to keep the data by inserting into object table in emacs.c.
   */
  extern Vrainy_day_data; /* in emacs.c */
  char buf[200];
  sprintf (buf, "Memory exhausted");
  if(Vrainy_day_data == 0)	/* Just in case I forgot to initialize. */
     while (1)
	Fsignal (Qerror, Fcons (build_string (buf), Qnil));
  else
     while (1)
	Fsignal (Qerror, Vrainy_day_data);
		
#endif
}

FILE: emacs.c

This is how I added the data.

***************
*** 67,76 ****
--- 72,88 ----
  int initialized;
  
  /* Variable whose value is symbol giving operating system type */
  Lisp_Object Vsystem_type;
    
+ #ifdef MFULLBUG
+ /* CI. recursive blowup when memory full error occurs.*/
+ Lisp_Object Vrainy_day_data;
+ #endif
+ /* Variable to tell if Kanji feature is available or not. */
+ Lisp_Object Vkanji_available;
+ 
  /* If non-zero, emacs should not attempt to use an window-specific code,
     but instead should use the virtual terminal under which it was started */
  int inhibit_window_system;
  
  #ifdef HAVE_X_WINDOWS
***************
*** 455,464 ****
--- 526,546 ----
  #endif /* CANNOT_DUMP */
      }
  
    initialized = 1;
  
+ #ifdef MFULLBUG
+   /* 
+    * This cons data is used when memory is exhausted and if we are 
+    * unlucky, the memory allocator blows up recursively by tring to 
+    * output this message. When it tries to create this string, the memory 
+    * allocator (again) finds that memory is no longer there, and then tries to
+    * outputs this message, ...
+    */
+   Vrainy_day_data = Fcons(build_string("memory exhausted"), Qnil);
+ #endif
+ 
    /* Enter editor command loop.  This never returns.  */
    Frecursive_edit ();
    /* NOTREACHED */
  }
  
***************
*** 625,634 ****
--- 717,760 ----
      "Symbol indicating type of operating system you are using.");
    Vsystem_type = intern (SYSTEM_TYPE);
  
    DEFVAR_BOOL ("noninteractive", &noninteractive1,
      "Non-nil means Emacs is running without interactive terminal.");
+ 
+ /*
+ ** CI: This is my way of telling the world if this GNU-Emacs has 
+ ** a kanji feature or not. This is referenced in Lisp library.
+ */
+   DEFVAR_LISP ("kanji-available", &Vkanji_available,
+    "Symbol indicating if Kanji/Hiragana/Katakana feature is built \n\
+ into system. Nil means No.\n");
+ 
+ #ifdef NEMACS
+   Vkanji_available = Qt;
+ #else
+   Vkanji_available = Qnil;
+ #endif
+ 
+ 
+ #ifdef MFULLBUG
+ /* CI recursive blow up in malloc_warning. */
+    Vrainy_day_data = intern("rainy_day_data");
+    DEFVAR_LISP("rainy-day-data", &Vrainy_day_data,
+ 	"Symbol which memory error routine uses.");
+ #endif
+ #ifdef MVDebug
+   DEFVAR_INT ("dg_get_fp", &dg_get_fp,
+ 	"The maximum frame pointer recorded so far within ENTER.");
+   DEFVAR_INT ("dg_get_fp_1" , &dg_get_fp_1,
+ 	"The value of frame pointer recorded in main.");
+ 
+   DEFVAR_INT ("dg_get_sp", &dg_get_sp,
+ 	"The maximum stack pointer recorded so far within ENTER.");
+   DEFVAR_INT ("dg_get_sp_1" , &dg_get_sp_1,
+ 	"The value of stack pointer recorded in main.");
+ 
+ #endif
  
    Vkill_emacs_hook = Qnil;
  
    DEFVAR_LISP ("kill-emacs-hook", &Vkill_emacs_hook,
      "Function called, if non-nil, whenever kill-emacs is called.");

	

Regards,
	
   Chiaki Ishikawa                        Phone:+81-3-5702-0351
 Personal Media Corp.                       FAX:+81-3-5702-0359
   1-7-7 Hiratsuka,     		 UUCP: ... uunet!pmcgw!ishikawa
 Shinagawa-ku, Tokyo 142	
Technical Details
Message-ID: <9004221044.AA03914@sun00.pmc.co.jp>
Path: arc1-ca.pugleaf.net!gmdzi!unido!fauern!ira.uka.de!snorkelwacker!tut.cis.ohio-state.edu!pmc.co.jp!ishikawa

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: fb2f1,6638c7548dbde084,start
X-Google-Attributes: gidfb2f1,public
X-Google-ArrivalTime: 1990-04-23 03:43:29 PST
Path: arc1-ca.pugleaf.net!gmdzi!unido!fauern!ira.uka.de!snorkelwacker!tut.cis.ohio-state.edu!pmc.co.jp!ishikawa
From: ishikawa@pmc.co.jp (CI)
Newsgroups: gnu.emacs.bug
Subject: Bug(?) GNU-emacs
Message-ID: <9004221044.AA03914@sun00.pmc.co.jp>
Date: 22 Apr 90 10:44:07 GMT
Sender: daemon@tut.cis.ohio-state.edu
Reply-To: uunet!pmcgw!ishikawa@uunet.uu.net
Distribution: gnu
Organization: GNUs Not Usenet
Lines: 188
Posted: Sun Apr 22 11:44:07 1990