From: Stefan Monnier Date: Wed, 31 Jul 2019 15:19:39 +0000 (-0400) Subject: * src/lread.c (infile): Set/reset it like a dynamically scoped variable X-Git-Tag: emacs-27.0.90~1808 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=bedcc2d87bde06482ccdc31ac7f428cbde34ced5;p=emacs.git * 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. --- diff --git a/src/lread.c b/src/lread.c index eecb5e141df..23e4616b6f8 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 == ';')