diff options
author | Lukas Larsson <[email protected]> | 2014-11-04 17:46:28 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2014-11-04 17:46:28 +0100 |
commit | 0f4b940cd6173a1e991c2bce7a6004d95c52c088 (patch) | |
tree | ef95f02023b2e037003ffff0c887c58443946569 | |
parent | 2d3a39b5729a295d4e0ac416ff0280e3edca44c6 (diff) | |
download | otp-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.c | 45 |
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; } |