aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2019-07-31 11:19:39 -0400
committerStefan Monnier2019-07-31 11:19:39 -0400
commitbedcc2d87bde06482ccdc31ac7f428cbde34ced5 (patch)
tree910a94845677f276e95fcc2ea0428ab951741d6d /src
parent495d0667fcf4df9f10c261684162c64f08aadd71 (diff)
downloademacs-bedcc2d87bde06482ccdc31ac7f428cbde34ced5.tar.gz
emacs-bedcc2d87bde06482ccdc31ac7f428cbde34ced5.zip
* 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.
Diffstat (limited to 'src')
-rw-r--r--src/lread.c17
1 files changed, 11 insertions, 6 deletions
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)
287 287
288 if (EQ (readcharfun, Qget_file_char)) 288 if (EQ (readcharfun, Qget_file_char))
289 { 289 {
290 eassert (infile);
290 readbyte = readbyte_from_file; 291 readbyte = readbyte_from_file;
291 goto read_multibyte; 292 goto read_multibyte;
292 } 293 }
@@ -320,6 +321,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
320 string, and the cdr part is a value of readcharfun given to 321 string, and the cdr part is a value of readcharfun given to
321 read_vector. */ 322 read_vector. */
322 readbyte = readbyte_from_string; 323 readbyte = readbyte_from_string;
324 eassert (infile);
323 if (EQ (XCDR (readcharfun), Qget_emacs_mule_file_char)) 325 if (EQ (XCDR (readcharfun), Qget_emacs_mule_file_char))
324 emacs_mule_encoding = 1; 326 emacs_mule_encoding = 1;
325 goto read_multibyte; 327 goto read_multibyte;
@@ -328,6 +330,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
328 if (EQ (readcharfun, Qget_emacs_mule_file_char)) 330 if (EQ (readcharfun, Qget_emacs_mule_file_char))
329 { 331 {
330 readbyte = readbyte_from_file; 332 readbyte = readbyte_from_file;
333 eassert (infile);
331 emacs_mule_encoding = 1; 334 emacs_mule_encoding = 1;
332 goto read_multibyte; 335 goto read_multibyte;
333 } 336 }
@@ -506,6 +509,7 @@ readbyte_from_stdio (void)
506static int 509static int
507readbyte_from_file (int c, Lisp_Object readcharfun) 510readbyte_from_file (int c, Lisp_Object readcharfun)
508{ 511{
512 eassert (infile);
509 if (c >= 0) 513 if (c >= 0)
510 { 514 {
511 eassert (infile->lookahead < sizeof infile->buf); 515 eassert (infile->lookahead < sizeof infile->buf);
@@ -1078,10 +1082,11 @@ suffix_p (Lisp_Object string, const char *suffix)
1078static void 1082static void
1079close_infile_unwind (void *arg) 1083close_infile_unwind (void *arg)
1080{ 1084{
1081 FILE *stream = arg; 1085 struct infile *prev_infile = arg;
1082 eassert (infile == NULL || infile->stream == stream); 1086 fprintf (stderr, "Closing infile: back to %x!\n", prev_infile);
1083 infile = NULL; 1087 eassert (infile);
1084 fclose (stream); 1088 fclose (infile->stream);
1089 infile = prev_infile;
1085} 1090}
1086 1091
1087DEFUN ("load", Fload, Sload, 1, 5, 0, 1092DEFUN ("load", Fload, Sload, 1, 5, 0,
@@ -1413,7 +1418,7 @@ Return t if the file exists and loads successfully. */)
1413 { 1418 {
1414 if (! stream) 1419 if (! stream)
1415 report_file_error ("Opening stdio stream", file); 1420 report_file_error ("Opening stdio stream", file);
1416 set_unwind_protect_ptr (fd_index, close_infile_unwind, stream); 1421 set_unwind_protect_ptr (fd_index, close_infile_unwind, infile);
1417 } 1422 }
1418 1423
1419 if (! NILP (Vpurify_flag)) 1424 if (! NILP (Vpurify_flag))
@@ -2019,7 +2024,7 @@ readevalloop (Lisp_Object readcharfun,
2019 if (b && first_sexp) 2024 if (b && first_sexp)
2020 whole_buffer = (BUF_PT (b) == BUF_BEG (b) && BUF_ZV (b) == BUF_Z (b)); 2025 whole_buffer = (BUF_PT (b) == BUF_BEG (b) && BUF_ZV (b) == BUF_Z (b));
2021 2026
2022 infile = infile0; 2027 eassert (!infile0 || infile == infile0);
2023 read_next: 2028 read_next:
2024 c = READCHAR; 2029 c = READCHAR;
2025 if (c == ';') 2030 if (c == ';')