fix `port-commit-peeked' and mid-stream EOFs

This commit is contained in:
Matthew Flatt 2012-07-26 06:10:49 -06:00
parent 11be722a0f
commit 4c3dd00d49
2 changed files with 25 additions and 11 deletions

View File

@ -353,9 +353,9 @@ but ports created with @racket[make-input-port] (see
Attempts to commit as read the first @racket[amt] previously peeked Attempts to commit as read the first @racket[amt] previously peeked
bytes, non-byte specials, and @racket[eof]s from @racket[in], or the bytes, non-byte specials, and @racket[eof]s from @racket[in], or the
first @racket[eof] or special value peeked from first @racket[eof] or special value peeked from
@racket[in]. (Only mid-stream @racket[eof]s can be @racket[in]. Mid-stream @racket[eof]s can be
committed. An @racket[eof] when the port is exhausted does not committed, but an @racket[eof] when the port is exhausted does not
correspond to data in the stream.) necessarily commit, since it does not correspond to data in the stream.
The read commits only if @racket[progress] does not become ready first The read commits only if @racket[progress] does not become ready first
(i.e., if no other process reads from @racket[in] first), and only if (i.e., if no other process reads from @racket[in] first), and only if

View File

@ -2326,6 +2326,8 @@ intptr_t scheme_get_byte_string_unless(const char *who,
if (ip->pending_eof > 1) { if (ip->pending_eof > 1) {
ip->pending_eof = 1; ip->pending_eof = 1;
if (ip->progress_evt)
post_progress(ip);
gc = EOF; gc = EOF;
} else { } else {
/* Call port's get or peek function. But first, set up /* Call port's get or peek function. But first, set up
@ -2363,7 +2365,7 @@ intptr_t scheme_get_byte_string_unless(const char *who,
gc = gs(ip, buffer, offset + got, size, nonblock, unless); gc = gs(ip, buffer, offset + got, size, nonblock, unless);
if (!peek && gc && ip->progress_evt if (!peek && gc && ip->progress_evt
&& (gc != EOF) && ((gc != EOF) || ip->pending_eof)
&& (gc != SCHEME_UNLESS_READY)) && (gc != SCHEME_UNLESS_READY))
post_progress(ip); post_progress(ip);
} }
@ -2610,9 +2612,9 @@ static int complete_peeked_read_via_get(Scheme_Input_Port *ip,
buf = _buf; buf = _buf;
did = 0; did = 0;
/* Target event is ready, so commit must succeed */ /* Target event is ready, so commit must succeed */
/* First remove ungotten_count chars */ /* First remove ungotten_count chars */
if (ip->ungotten_count) { if (ip->ungotten_count) {
int i, amt; int i, amt;
@ -2643,7 +2645,7 @@ static int complete_peeked_read_via_get(Scheme_Input_Port *ip,
post_progress(ip); post_progress(ip);
did = 1; did = 1;
} }
if (size) { if (size) {
Scheme_Input_Port *pip; Scheme_Input_Port *pip;
@ -2658,17 +2660,26 @@ static int complete_peeked_read_via_get(Scheme_Input_Port *ip,
if (ip->peeked_read) { if (ip->peeked_read) {
int cnt; int cnt;
cnt = pipe_char_count(ip->peeked_read); cnt = pipe_char_count(ip->peeked_read);
if ((cnt < size) && (ip->pending_eof == 2)) if ((cnt < size) && (ip->pending_eof == 2)) {
ip->pending_eof = 1; ip->pending_eof = 1;
size--;
did = 1;
}
pip = (Scheme_Input_Port *)ip->peeked_read; pip = (Scheme_Input_Port *)ip->peeked_read;
gs = pip->get_string_fun; gs = pip->get_string_fun;
} else { } else {
if (ip->pending_eof == 2) {
ip->pending_eof = 1;
did = 1;
if (ip->progress_evt)
post_progress(ip);
}
gs = NULL; gs = NULL;
pip = NULL; pip = NULL;
} }
} }
if (gs) { if (gs && size) {
if (ip->p.count_lines) { if (ip->p.count_lines) {
if (buf_size < size) { if (buf_size < size) {
buf = scheme_malloc_atomic(size); buf = scheme_malloc_atomic(size);
@ -2688,8 +2699,11 @@ static int complete_peeked_read_via_get(Scheme_Input_Port *ip,
} }
} }
} }
return did; /* We used to return `did', but since an event has already been
selected, claim success at this point always. */
return 1;
} }
static Scheme_Object *return_data(void *data, int argc, Scheme_Object **argv) static Scheme_Object *return_data(void *data, int argc, Scheme_Object **argv)