aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2014-11-04 17:46:28 +0100
committerLukas Larsson <[email protected]>2014-11-04 17:46:28 +0100
commit0f4b940cd6173a1e991c2bce7a6004d95c52c088 (patch)
treeef95f02023b2e037003ffff0c887c58443946569
parent2d3a39b5729a295d4e0ac416ff0280e3edca44c6 (diff)
downloadotp-0f4b940cd6173a1e991c2bce7a6004d95c52c088.tar.gz
otp-0f4b940cd6173a1e991c2bce7a6004d95c52c088.tar.bz2
otp-0f4b940cd6173a1e991c2bce7a6004d95c52c088.zip
erts: Make erts_printf work with non-blocking
Now that stdout can be set as non-blocking by the ttsl driver we can no longer use putc and friends for the stdout/stderr streams. Therefore we fallback on write. OTP-12239
-rw-r--r--erts/lib_src/common/erl_printf.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/erts/lib_src/common/erl_printf.c b/erts/lib_src/common/erl_printf.c
index 2c177ee5ac..0a0346ac2d 100644
--- a/erts/lib_src/common/erl_printf.c
+++ b/erts/lib_src/common/erl_printf.c
@@ -87,6 +87,39 @@ void (*erts_printf_unblock_fpe)(int) = NULL;
# define FWRITE fwrite
#endif
+/* We use write for stdout and stderr as they could be
+ set to non-blocking by shell drivers, and non-blocking
+ FILE * functions work unpredictably as best */
+static int
+printf_putc(int c, FILE *stream) {
+ if ((FILE*)stream == stdout || (FILE*)stream == stderr) {
+ int fd = stream == stdout ? fileno(stdout) : fileno(stdin);
+ int res;
+ do {
+ res = write(fd,&c,1);
+ } while (res == -1 && (errno == EAGAIN || errno == EINTR));
+ if (res == -1) return EOF;
+ return res;
+ }
+
+ return PUTC(c, stream);
+}
+
+static size_t
+printf_fwrite(const void *ptr, size_t size, size_t nitems,
+ FILE *stream) {
+ if ((FILE*)stream == stdout || (FILE*)stream == stderr) {
+ int fd = stream == stdout ? fileno(stdout) : fileno(stdin);
+ int res;
+ do {
+ res = write(fd, ptr, size*nitems);
+ } while (res == -1 && (errno == EAGAIN || errno == EINTR));
+ if (res == -1) return 0;
+ return res;
+ }
+ return FWRITE(ptr, size, nitems, stream);
+}
+
static int
get_error_result(void)
{
@@ -103,10 +136,10 @@ write_f_add_cr(void *vfp, char* buf, size_t len)
size_t i;
ASSERT(vfp);
for (i = 0; i < len; i++) {
- if (buf[i] == '\n' && PUTC('\r', (FILE *) vfp) == EOF)
- return get_error_result();
- if (PUTC(buf[i], (FILE *) vfp) == EOF)
- return get_error_result();
+ if (buf[i] == '\n' && printf_putc('\r', (FILE *) vfp) == EOF)
+ return get_error_result();
+ if (printf_putc(buf[i], (FILE *) vfp) == EOF)
+ return get_error_result();
}
return len;
}
@@ -119,12 +152,12 @@ write_f(void *vfp, char* buf, size_t len)
if (len <= 64) { /* Try to optimize writes of small bufs. */
int i;
for (i = 0; i < len; i++)
- if (PUTC(buf[i], (FILE *) vfp) == EOF)
+ if (printf_putc(buf[i], (FILE *) vfp) == EOF)
return get_error_result();
}
else
#endif
- if (FWRITE((void *) buf, sizeof(char), len, (FILE *) vfp) != len)
+ if (printf_fwrite((void *) buf, sizeof(char), len, (FILE *) vfp) != len)
return get_error_result();
return len;
}