From 81a39be0bbda797dcb67321fafe0fcd3d0cd9b40 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Thu, 30 Jul 2020 23:00:34 -0700 Subject: [PATCH] Support explicitly separated output on stderr In principle this would allow 'string split' or whatever to output to stderr and not lose the item separation. In practice this is not used but it fixes a TODO. --- src/exec.cpp | 15 ++++++++------- src/io.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/exec.cpp b/src/exec.cpp index a17e59c25..be05303d0 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -469,12 +469,6 @@ static bool handle_builtin_output(parser_t &parser, const std::shared_ptr // If we are directing output to a buffer, then we can just transfer it directly without needing // to write to the bufferfill pipe. Note this is how we handle explicitly separated stdout // output (i.e. string split0) which can't really be sent through a pipe. - // TODO: we're sloppy about handling explicitly separated output. - // Theoretically we could have explicitly separated output on stdout and also stderr output; in - // that case we ought to thread the exp-sep output through to the io buffer. We're getting away - // with this because the only thing that can output exp-sep output is `string split0` which - // doesn't also produce stderr. Also note that we never send stderr to a buffer, so there's no - // need for a similar check for stderr. bool stdout_done = false; if (output_buffer && stdout_io && stdout_io->io_mode == io_mode_t::bufferfill) { auto stdout_buffer = dynamic_cast(stdout_io.get())->buffer(); @@ -482,13 +476,20 @@ static bool handle_builtin_output(parser_t &parser, const std::shared_ptr stdout_done = true; } + bool stderr_done = false; + if (errput_buffer && stderr_io && stderr_io->io_mode == io_mode_t::bufferfill) { + auto stderr_buffer = dynamic_cast(stderr_io.get())->buffer(); + stderr_buffer->append_from_wide_buffer(*errput_buffer); + stderr_done = true; + } + // Figure out any data remaining to write. We may have none in which case we can short-circuit. std::string outbuff; if (output_buffer && !stdout_done) { outbuff = wcs2string(output_buffer->newline_serialized()); } std::string errbuff; - if (errput_buffer) { + if (errput_buffer && !stderr_done) { errbuff = wcs2string(errput_buffer->newline_serialized()); } diff --git a/src/io.h b/src/io.h index f31c73e97..23b2952ef 100644 --- a/src/io.h +++ b/src/io.h @@ -313,7 +313,7 @@ class io_buffer_t { /// Lock for appending. std::mutex append_lock_{}; - /// Read a bit, filling the buffer. The append lock must be held. + /// Read some, filling the buffer. The append lock must be held. /// \return positive on success, 0 if closed, -1 on error (in which case errno will be set). ssize_t read_once(int fd);