Use read(2) instead of fgets(3) when reading process output.

This patch modifies `tor_read_all_handle()` to use read(2) instead of
fgets(3) when reading the stdout from the child process. This should
eliminate the race condition that can be triggered in the 'slow/util/*'
tests on slower machines running OpenBSD, FreeBSD and HardenedBSD.

See: https://bugs.torproject.org/21654
This commit is contained in:
Alexander Færøy 2017-03-08 00:12:06 +01:00 committed by Alexander Færøy
parent ad19f1507a
commit 86de065aee
No known key found for this signature in database
GPG Key ID: E15081D5D3C3DB53

View File

@ -5010,7 +5010,7 @@ tor_read_all_handle(FILE *h, char *buf, size_t count,
int *eof) int *eof)
{ {
size_t numread = 0; size_t numread = 0;
char *retval; ssize_t result;
if (eof) if (eof)
*eof = 0; *eof = 0;
@ -5019,33 +5019,27 @@ tor_read_all_handle(FILE *h, char *buf, size_t count,
return -1; return -1;
while (numread != count) { while (numread != count) {
/* Use fgets because that is what we use in log_from_pipe() */ result = read(fileno(h), buf+numread, count-numread);
retval = tor_fgets(buf+numread, (int)(count-numread), h);
if (NULL == retval) { if (result == 0) {
if (feof(h)) { log_debug(LD_GENERAL, "read() reached end of file");
log_debug(LD_GENERAL, "fgets() reached end of file"); if (eof)
if (eof) *eof = 1;
*eof = 1; break;
} else if (result < 0 && errno == EAGAIN) {
if (process)
continue;
else
break; break;
} else { } else if (result < 0) {
if (EAGAIN == errno) { log_warn(LD_GENERAL, "read() failed: %s", strerror(errno));
if (process) return -1;
continue;
else
break;
} else {
log_warn(LD_GENERAL, "fgets() from handle failed: %s",
strerror(errno));
return -1;
}
}
} }
tor_assert(retval != NULL);
tor_assert(strlen(retval) + numread <= count); numread += result;
numread += strlen(retval);
} }
log_debug(LD_GENERAL, "fgets() read %d bytes from handle", (int)numread); log_debug(LD_GENERAL, "read() read %d bytes from handle", (int)numread);
return (ssize_t)numread; return (ssize_t)numread;
} }
#endif #endif