wget: correctly handle rare case when we get EAGAIN _on first_ read
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
ab8d00d64f
commit
8766a791e8
@ -487,6 +487,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
|
|||||||
rdsz = (unsigned)G.content_len;
|
rdsz = (unsigned)G.content_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
|
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
|
||||||
# if ENABLE_FEATURE_WGET_TIMEOUT
|
# if ENABLE_FEATURE_WGET_TIMEOUT
|
||||||
second_cnt = G.timeout_seconds;
|
second_cnt = G.timeout_seconds;
|
||||||
@ -497,22 +498,41 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
|
|||||||
# if ENABLE_FEATURE_WGET_TIMEOUT
|
# if ENABLE_FEATURE_WGET_TIMEOUT
|
||||||
if (second_cnt != 0 && --second_cnt == 0) {
|
if (second_cnt != 0 && --second_cnt == 0) {
|
||||||
progress_meter(PROGRESS_END);
|
progress_meter(PROGRESS_END);
|
||||||
bb_perror_msg_and_die("download timed out");
|
bb_error_msg_and_die("download timed out");
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
/* Needed for "stalled" indicator */
|
/* Needed for "stalled" indicator */
|
||||||
progress_meter(PROGRESS_BUMP);
|
progress_meter(PROGRESS_BUMP);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* fread internally uses read loop, which in our case
|
||||||
|
* is usually exited when we get EAGAIN.
|
||||||
|
* In this case, libc sets error marker on the stream.
|
||||||
|
* Need to clear it before next fread to avoid possible
|
||||||
|
* rare false positive ferror below. Rare because usually
|
||||||
|
* fread gets more than zero bytes, and we don't fall
|
||||||
|
* into if (n <= 0) ...
|
||||||
|
*/
|
||||||
|
clearerr(dfp);
|
||||||
|
errno = 0;
|
||||||
n = fread(G.wget_buf, 1, rdsz, dfp);
|
n = fread(G.wget_buf, 1, rdsz, dfp);
|
||||||
|
/* man fread:
|
||||||
|
* If error occurs, or EOF is reached, the return value
|
||||||
|
* is a short item count (or zero).
|
||||||
|
* fread does not distinguish between EOF and error.
|
||||||
|
*/
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
if (ferror(dfp)) {
|
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
|
||||||
/* perror will not work: ferror doesn't set errno */
|
if (errno == EAGAIN) /* poll lied, there is no data? */
|
||||||
bb_error_msg_and_die(bb_msg_read_error);
|
continue; /* yes */
|
||||||
}
|
#endif
|
||||||
break;
|
if (ferror(dfp))
|
||||||
|
bb_perror_msg_and_die(bb_msg_read_error);
|
||||||
|
break; /* EOF, not error */
|
||||||
}
|
}
|
||||||
|
|
||||||
xwrite(output_fd, G.wget_buf, n);
|
xwrite(output_fd, G.wget_buf, n);
|
||||||
|
|
||||||
#if ENABLE_FEATURE_WGET_STATUSBAR
|
#if ENABLE_FEATURE_WGET_STATUSBAR
|
||||||
G.transferred += n;
|
G.transferred += n;
|
||||||
progress_meter(PROGRESS_BUMP);
|
progress_meter(PROGRESS_BUMP);
|
||||||
|
Loading…
Reference in New Issue
Block a user