[136398] trunk/base/src/darwintracelib1.0/darwintrace.c
cal at macports.org
cal at macports.org
Fri May 15 15:46:22 PDT 2015
Revision: 136398
https://trac.macports.org/changeset/136398
Author: cal at macports.org
Date: 2015-05-15 15:46:22 -0700 (Fri, 15 May 2015)
Log Message:
-----------
base: darwintrace: don't use fread(3) and fwrite(3)
fread(3) and fwrite(3) can both be interrupted by signals, return a short
read/write or error and set errno=EINTR. Since there is no way to find out
whether the interrupted call has already read or written partial data, these
calls can never be re-called correctly without possible corruption. This is
a fundamental problem in the API and the implementation on OS X.
To avoid this, use write(2) and read(2) instead.
Modified Paths:
--------------
trunk/base/src/darwintracelib1.0/darwintrace.c
Modified: trunk/base/src/darwintracelib1.0/darwintrace.c
===================================================================
--- trunk/base/src/darwintracelib1.0/darwintrace.c 2015-05-15 21:10:01 UTC (rev 136397)
+++ trunk/base/src/darwintracelib1.0/darwintrace.c 2015-05-15 22:46:22 UTC (rev 136398)
@@ -498,14 +498,30 @@
* \param[in] size number of bytes to read from the socket
*/
static void frecv(void *restrict buf, size_t size) {
- FILE *stream = __darwintrace_sock();
- if (1 != fread(buf, size, 1, stream)) {
- if (ferror(stream)) {
- perror("darwintrace: fread");
- } else {
- fprintf(stderr, "darwintrace: fread: end-of-file\n");
+ /* We cannot safely use fread(3) here, because we're not in control of the
+ * application's signal handling settings (which means we must assume
+ * SA_RESTART isn't set) and fread(3) may return short without giving us
+ * a way to know how many bytes have actually been read, i.e. without a way
+ * to do the call again. Because of this great API design and
+ * implementation on OS X, we'll just use read(2) here. */
+ int fd = fileno(__darwintrace_sock());
+ size_t count = 0;
+ while (count < size) {
+ ssize_t res = read(fd, buf + count, size - count);
+ if (res < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ perror("darwintrace: read");
+ abort();
}
- abort();
+
+ if (res == 0) {
+ fprintf(stderr, "darwintrace: read: end-of-file\n");
+ abort();
+ }
+
+ count += res;
}
}
@@ -517,16 +533,26 @@
* \param[in] size number of bytes in the buffer
*/
static void fsend(const void *restrict buf, size_t size) {
- FILE *stream = __darwintrace_sock();
- if (1 != fwrite(buf, size, 1, stream)) {
- if (ferror(stream)) {
- perror("darwintrace: fwrite");
- } else {
- fprintf(stderr, "darwintrace: fwrite: end-of-file\n");
+ /* We cannot safely use fwrite(3) here, because we're not in control of the
+ * application's signal handling settings (which means we must assume
+ * SA_RESTART isn't set) and fwrite(3) may return short without giving us
+ * a way to know how many bytes have actually been written, i.e. without
+ * a way to do the call again. Because of this great API design and
+ * implementation on OS X, we'll just use write(2) here. */
+ int fd = fileno(__darwintrace_sock());
+ size_t count = 0;
+ while (count < size) {
+ ssize_t res = write(fd, buf + count, size - count);
+ if (res < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ perror("darwintrace: write");
+ abort();
}
- abort();
+
+ count += res;
}
- fflush(stream);
}
/**
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20150515/3f4a6fe4/attachment.html>
More information about the macports-changes
mailing list