Dmitry N. Mikushin
2012-Nov-29 06:54 UTC
[LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection
Dear all, Consider there is a program that writes to stdout using two different raw_fd_ostream-s: #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; int main() { raw_fd_ostream S(STDOUT_FILENO, false); outs() << "Hello"; S << ", world!"; return 0; } With this layout everything is fine, it prints ", world!Hello" Now, make S definition global: #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; raw_fd_ostream S(STDOUT_FILENO, false); int main() { outs() << "Hello"; S << ", world!"; return 0; } And... surprisingly: $ ./outs Hello, world!$ ./outs &>result $ cat result HelloLLVM ERROR: IO failure on output stream. So, no error with screen output and error when redirected to file. Why so? Thanks, - D. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121129/7c148904/attachment.html>
Sean Silva
2012-Nov-29 11:02 UTC
[LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection
My guess is that in the second case the timing of the global destructor of S is messing things up. Just a guess though. -- Sean Silva On Thu, Nov 29, 2012 at 1:54 AM, Dmitry N. Mikushin <maemarcus at gmail.com> wrote:> Dear all, > > Consider there is a program that writes to stdout using two different > raw_fd_ostream-s: > > #include "llvm/LLVMContext.h" > #include "llvm/Module.h" > #include "llvm/Support/raw_ostream.h" > > using namespace llvm; > > int main() > { > raw_fd_ostream S(STDOUT_FILENO, false); > > outs() << "Hello"; > S << ", world!"; > > return 0; > } > > With this layout everything is fine, it prints ", world!Hello" > > Now, make S definition global: > > #include "llvm/LLVMContext.h" > #include "llvm/Module.h" > #include "llvm/Support/raw_ostream.h" > > using namespace llvm; > > raw_fd_ostream S(STDOUT_FILENO, false); > > int main() > { > outs() << "Hello"; > S << ", world!"; > > return 0; > } > > And... surprisingly: > > $ ./outs > Hello, world!$ ./outs &>result > $ cat result > HelloLLVM ERROR: IO failure on output stream. > > So, no error with screen output and error when redirected to file. Why so? > > Thanks, > - D. > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >
Dan Gohman
2012-Nov-29 18:46 UTC
[LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection
On Wed, Nov 28, 2012 at 10:54 PM, Dmitry N. Mikushin <maemarcus at gmail.com>wrote:> Dear all, > > Consider there is a program that writes to stdout using two different > raw_fd_ostream-s:raw_fd_ostream does buffered I/O, so it's not really meant to be used like this.> #include "llvm/LLVMContext.h" > #include "llvm/Module.h" > #include "llvm/Support/raw_ostream.h" > > using namespace llvm; > > int main() > { > raw_fd_ostream S(STDOUT_FILENO, false); > > outs() << "Hello"; > S << ", world!"; > > return 0; > } > > With this layout everything is fine, it prints ", world!Hello" >Yes. raw_ostream does buffering. The output you see is a classic symptom of having two different buffers for the same file descriptor. You can make this work by manually flushing when switching from one buffer to another, if you're careful.> > Now, make S definition global: > > #include "llvm/LLVMContext.h" > #include "llvm/Module.h" > #include "llvm/Support/raw_ostream.h" > > using namespace llvm; > > raw_fd_ostream S(STDOUT_FILENO, false); > > int main() > { > outs() << "Hello"; > S << ", world!"; > > return 0; > } > > And... surprisingly: > > $ ./outs > Hello, world!$ ./outs &>result > $ cat result > HelloLLVM ERROR: IO failure on output stream. > > So, no error with screen output and error when redirected to file. Why so?The difference in output is due to the difference in when the buffers happen to get destructed, because they flush their buffers in their destructors. The error comes from the fact that outs() closes STDOUT_FILENO when the program exits. Your other raw_fd_ostream is getting unlucky and having its destructor run after the outs() object is destructed, so it ends up trying to write to a closed file descriptor. There's no easy way to avoid this problem, as global destructor ordering is inconvenient to control. In general, it's best to try to avoid this situation altogether. Dan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121129/8989238e/attachment.html>
Dmitry N. Mikushin
2012-Nov-29 19:03 UTC
[LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection
Hi Dan, Sean, Thanks for replies, So does it mean user is not expected to use any other stream for stdout, but outs()? Although there is a comment "If you don't want this behavior, don't use outs().", outs() is a static instance which always exists and creates problems, even if not used. - D. 2012/11/29 Dan Gohman <dan433584 at gmail.com>> On Wed, Nov 28, 2012 at 10:54 PM, Dmitry N. Mikushin <maemarcus at gmail.com>wrote: > >> Dear all, >> >> Consider there is a program that writes to stdout using two different >> raw_fd_ostream-s: > > > raw_fd_ostream does buffered I/O, so it's not really meant to be used like > this. > > >> #include "llvm/LLVMContext.h" >> #include "llvm/Module.h" >> #include "llvm/Support/raw_ostream.h" >> >> using namespace llvm; >> >> int main() >> { >> raw_fd_ostream S(STDOUT_FILENO, false); >> >> outs() << "Hello"; >> S << ", world!"; >> >> return 0; >> } >> >> With this layout everything is fine, it prints ", world!Hello" >> > > Yes. raw_ostream does buffering. The output you see is a classic symptom > of having two different buffers for the same file descriptor. You can make > this work by manually flushing when switching from one buffer to another, > if you're careful. > > >> >> Now, make S definition global: >> >> #include "llvm/LLVMContext.h" >> #include "llvm/Module.h" >> #include "llvm/Support/raw_ostream.h" >> >> using namespace llvm; >> >> raw_fd_ostream S(STDOUT_FILENO, false); >> >> int main() >> { >> outs() << "Hello"; >> S << ", world!"; >> >> return 0; >> } >> >> And... surprisingly: >> >> $ ./outs >> Hello, world!$ ./outs &>result >> $ cat result >> HelloLLVM ERROR: IO failure on output stream. >> >> So, no error with screen output and error when redirected to file. Why so? > > > The difference in output is due to the difference in when the buffers > happen to get destructed, because they flush their buffers in their > destructors. > > The error comes from the fact that outs() closes STDOUT_FILENO when the > program exits. Your other raw_fd_ostream is getting unlucky and having its > destructor run after the outs() object is destructed, so it ends up trying > to write to a closed file descriptor. There's no easy way to avoid this > problem, as global destructor ordering is inconvenient to control. In > general, it's best to try to avoid this situation altogether. > > Dan > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121129/9d389b1e/attachment.html>
Possibly Parallel Threads
- [LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection
- [LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection
- [LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection
- raw_pwrite_stream to string or stdout?
- [LLVMdev] [NVPTX] Backend failure in LegalizeDAG due to unimplemented expand in target lowering