emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master bedcc2d: * src/lread.c (infile): Set/reset it like


From: Stefan Monnier
Subject: [Emacs-diffs] master bedcc2d: * src/lread.c (infile): Set/reset it like a dynamically scoped variable
Date: Wed, 31 Jul 2019 11:19:44 -0400 (EDT)

branch: master
commit bedcc2d87bde06482ccdc31ac7f428cbde34ced5
Author: Stefan Monnier <address@hidden>
Commit: Stefan Monnier <address@hidden>

    * src/lread.c (infile): Set/reset it like a dynamically scoped variable
    
    I've seen segfaults where `infile` is nil when we get to
    readbyte_from_file, presumably because Fload set it to NULL (via
    close_infile_unwind) just before returning to its caller which was
    probably itself within another read/load and for some reason
    readevalloop didn't get to re-set `infile` like it used to do at every
    iteration.  I was not able to really track down the bug, but the way
    `infile` was set/reset seemed fragile and managing it like a standard
    dynamically-scoped var seems both safer (and more efficient since we
    don't need readevalloop to constantly re-set it).
    
    (readchar): Assert that `infile` is set if using a function the depends on 
it.
    (readbyte_from_file): Assert that `infile` is set.
    (close_infile_unwind): Reset `infile` to its previous value rather than
    to NULL.
    (Fload): Remember the previous value of `infile` before chaning it.
    (readevalloop): Don't set `infile` any more.
---
 src/lread.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/lread.c b/src/lread.c
index eecb5e1..23e4616 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -287,6 +287,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
 
   if (EQ (readcharfun, Qget_file_char))
     {
+      eassert (infile);
       readbyte = readbyte_from_file;
       goto read_multibyte;
     }
@@ -320,6 +321,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
         string, and the cdr part is a value of readcharfun given to
         read_vector.  */
       readbyte = readbyte_from_string;
+      eassert (infile);
       if (EQ (XCDR (readcharfun), Qget_emacs_mule_file_char))
        emacs_mule_encoding = 1;
       goto read_multibyte;
@@ -328,6 +330,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
   if (EQ (readcharfun, Qget_emacs_mule_file_char))
     {
       readbyte = readbyte_from_file;
+      eassert (infile);
       emacs_mule_encoding = 1;
       goto read_multibyte;
     }
@@ -506,6 +509,7 @@ readbyte_from_stdio (void)
 static int
 readbyte_from_file (int c, Lisp_Object readcharfun)
 {
+  eassert (infile);
   if (c >= 0)
     {
       eassert (infile->lookahead < sizeof infile->buf);
@@ -1078,10 +1082,11 @@ suffix_p (Lisp_Object string, const char *suffix)
 static void
 close_infile_unwind (void *arg)
 {
-  FILE *stream = arg;
-  eassert (infile == NULL || infile->stream == stream);
-  infile = NULL;
-  fclose (stream);
+  struct infile *prev_infile = arg;
+  fprintf (stderr, "Closing infile: back to %x!\n", prev_infile);
+  eassert (infile);
+  fclose (infile->stream);
+  infile = prev_infile;
 }
 
 DEFUN ("load", Fload, Sload, 1, 5, 0,
@@ -1413,7 +1418,7 @@ Return t if the file exists and loads successfully.  */)
     {
       if (! stream)
         report_file_error ("Opening stdio stream", file);
-      set_unwind_protect_ptr (fd_index, close_infile_unwind, stream);
+      set_unwind_protect_ptr (fd_index, close_infile_unwind, infile);
     }
 
   if (! NILP (Vpurify_flag))
@@ -2019,7 +2024,7 @@ readevalloop (Lisp_Object readcharfun,
       if (b && first_sexp)
        whole_buffer = (BUF_PT (b) == BUF_BEG (b) && BUF_ZV (b) == BUF_Z (b));
 
-      infile = infile0;
+      eassert (!infile0 || infile == infile0);
     read_next:
       c = READCHAR;
       if (c == ';')



reply via email to

[Prev in Thread] Current Thread [Next in Thread]