Subject: Re: bug#23912: 25.0.95; Abort in gc when working with streams

From: Eli Zaretskii <[email-masked]>
Date: Thu, 14 Jul 2016 17:58:47 +0300

> From: Michael Heerdegen <[email-masked]>
> Cc: [email-masked]
> Date: Wed, 13 Jul 2016 23:23:35 +0200
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> > > From: Michael Heerdegen <[email-masked]>
> > > Cc: [email-masked]
> > > Date: Tue, 12 Jul 2016 23:53:31 +0200
> > > 
> > > #0 0x00007ffff1930c19 in raise () from
> > > /lib/x86_64-linux-gnu/libpthread.so.0
> > > #1 0x000000000054d2fe in terminate_due_to_signal (sig=6,
> > > backtrace_limit=40) at emacs.c:381
> > > #2  0x00000000005715d9 in emacs_abort () at sysdep.c:2247
> > > #3 0x00000000005c9c1d in garbage_collect_1 (end=0x7fffffff5868) at
> > > alloc.c:5662
> > > #4  0x00000000005ca55d in Fgarbage_collect () at alloc.c:5979
> > > #5  0x000000000054afbc in maybe_gc () at lisp.h:4654
> >
> > I don't understand how this could have happened.  The only place that
> > sets abort_on_gc true is prin1-to-string, but it is not in the
> > backtrace.  So somehow that setting was not reset at the end of
> > prin1-to-string, and it looks like the only way that could have
> > happened is if some code triggered by prin1-to-string set
> > throw-on-input or called while-no-input.  Is this likely to have
> > happened during what you did?
> 
> Yes, it's very likely.

Richard, do you perhaps remember, or can try to second-guess, why do
we set the abort_on_gc flag inside prin1-to-string?  I mean this
fragment of print.c:

  /* Save and restore this: we are altering a buffer
     but we don't want to deactivate the mark just for that.
     No need for specbind, since errors deactivate the mark.  */
  Lisp_Object save_deactivate_mark = Vdeactivate_mark;
  bool prev_abort_on_gc = abort_on_gc;
  abort_on_gc = true;  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  Lisp_Object printcharfun = Vprin1_to_string_buffer;
  PRINTPREPARE;
  print (object, printcharfun, NILP (noescape));
  /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINISH */
  PRINTFINISH;

  struct buffer *previous = current_buffer;
  set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
  object = Fbuffer_string ();
  if (SBYTES (object) == SCHARS (object))
    STRING_SET_UNIBYTE (object);

  /* Note that this won't make prepare_to_modify_buffer call
     ask-user-about-supersession-threat because this buffer
     does not visit a file.  */
  Ferase_buffer ();
  set_buffer_internal (previous);

  Vdeactivate_mark = save_deactivate_mark;

  abort_on_gc = prev_abort_on_gc;

Why do we want to prevent GC while working on Vprin1_to_string_buffer?
It's just a buffer, and AFAICT we just collect the printed stuff
there.  And yet this code that tries to avoid GC was there since long
ago, first as GCPRO, and now as this flag.  What bad things could
happen if we just remove it?