>From f3d62ec79d309353f3940eeda514e64d0b9d021b Mon Sep 17 00:00:00 2001 From: Peter Bex Date: Wed, 3 Oct 2012 21:00:52 +0200 Subject: [PATCH] After calling getc() and getting back EOF, properly check feof() before checking errno; if errno is not cleared we'd get in an endless loop on an interrupted system call. These are quite rare, that's why this wasn't noticed before. Also copy the bit already read when looping, after receiving EINTR in read-line --- library.scm | 14 +++++++++----- runtime.c | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/library.scm b/library.scm index b17041f..0c5420c 100644 --- a/library.scm +++ b/library.scm @@ -76,15 +76,16 @@ fast_read_line_from_file(C_word str, C_word port, C_word size) { char *buf = C_c_string(str); C_FILEPTR fp = C_port_file(port); - if ((c = C_getc(fp)) == EOF) - return errno == EINTR ? C_fix(-1) : C_SCHEME_END_OF_FILE; + if ((c = C_getc(fp)) == EOF) { + return (errno == EINTR && !feof(fp)) ? C_fix(-1) : C_SCHEME_END_OF_FILE; + } C_ungetc(c, fp); for (i = 0; i < n; i++) { c = C_getc(fp); - if(c == EOF && errno == EINTR) { + if(c == EOF && errno == EINTR && !feof(fp)) { clearerr(fp); return C_fix(-(i + 1)); } @@ -110,7 +111,7 @@ fast_read_string_from_file(C_word dest, C_word port, C_word len, C_word pos) size_t m = fread (buf, sizeof (char), n, fp); - if(m == EOF && errno == EINTR) { + if(m == EOF && errno == EINTR && !feof(fp)) { clearerr(fp); return C_fix(-1); } @@ -1811,7 +1812,10 @@ EOF (let ((n (fx- (fxneg n) 1))) (##sys#dispatch-interrupt (lambda () - (loop len limit buffer result f))))) + (loop len limit buffer + (##sys#string-append + result (##sys#substring buffer 0 n)) + #t))))) [f (##sys#setislot p 4 (fx+ (##sys#slot p 4) 1)) (##sys#string-append result (##sys#substring buffer 0 n))] [else diff --git a/runtime.c b/runtime.c index 2673d81..9cf3f3f 100644 --- a/runtime.c +++ b/runtime.c @@ -3971,7 +3971,7 @@ C_regparm C_word C_fcall C_read_char(C_word port) int c = C_getc(C_port_file(port)); if(c == EOF) { - if(errno == EINTR) return C_fix(-1); + if(errno == EINTR && !feof(C_port_file(port))) return C_fix(-1); /* Found here: http://mail.python.org/pipermail/python-bugs-list/2002-July/012579.html */ #if defined(_WIN32) && !defined(__CYGWIN__) @@ -3990,7 +3990,7 @@ C_regparm C_word C_fcall C_peek_char(C_word port) int c = C_getc(fp); if(c == EOF) { - if(errno == EINTR) return C_fix(-1); + if(errno == EINTR && !feof(C_port_file(port))) return C_fix(-1); /* see above */ #if defined(_WIN32) && !defined(__CYGWIN__) else if(GetLastError() == ERROR_OPERATION_ABORTED) return C_fix(-1); -- 1.7.9.1