Viacheslav Nikolaev via llvm-dev
2016-Dec-07 09:52 UTC
[llvm-dev] Race condition in raw_ostream
This code from raw_ostream.h is really racy: raw_ostream &operator<<(StringRef Str) { // Inline fast path, particularly for strings with a known length. size_t Size = Str.size(); // Make sure we can use the fast path. if (Size > (size_t)(OutBufEnd - OutBufCur)) return write(Str.data(), Size); if (Size) { memcpy(OutBufCur, Str.data(), Size); OutBufCur += Size; } return *this; } Of course, one might wonder why someone would need to output to a stream from multiple threads at the same time. But imagine someone might get logs to dbgs() or errs() running the backend for a target in multiple threads. Is there any known practice to avoid such a problem? -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161207/679440fb/attachment.html>
> On Dec 7, 2016, at 1:52 AM, Viacheslav Nikolaev via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > This code from raw_ostream.h is really racy: > > raw_ostream &operator<<(StringRef Str) { > // Inline fast path, particularly for strings with a known length. > size_t Size = Str.size(); > > // Make sure we can use the fast path. > if (Size > (size_t)(OutBufEnd - OutBufCur)) > return write(Str.data(), Size); > > if (Size) { > memcpy(OutBufCur, Str.data(), Size); > OutBufCur += Size; > } > return *this; > }I don’t believe "the is racy” is an appropriate qualification, “buffered raw_ostream are not providing a thread-safe API" seems more accurate to me.> Of course, one might wonder why someone would need to output to a stream from multiple threads at the same time. > > But imagine someone might get logs to dbgs() or errs() running the backend for a target in multiple threads.These are unbuffered, I wouldn’t expect a race in the code you list above. I believe it’ll always forward directly to raw_fd_ostream::write_impl(), which is calling the libc ::write(). — Mehdi
On Wed, Dec 7, 2016 at 10:02 AM, Mehdi Amini via llvm-dev < llvm-dev at lists.llvm.org> wrote:> > > On Dec 7, 2016, at 1:52 AM, Viacheslav Nikolaev via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > > > > This code from raw_ostream.h is really racy: > > > > raw_ostream &operator<<(StringRef Str) { > > // Inline fast path, particularly for strings with a known length. > > size_t Size = Str.size(); > > > > // Make sure we can use the fast path. > > if (Size > (size_t)(OutBufEnd - OutBufCur)) > > return write(Str.data(), Size); > > > > if (Size) { > > memcpy(OutBufCur, Str.data(), Size); > > OutBufCur += Size; > > } > > return *this; > > } > > I don’t believe "the is racy” is an appropriate qualification, “buffered > raw_ostream are not providing a thread-safe API" seems more accurate to me.I agree. Acquiring a lock on each write to a buffered raw_ostream is too expensive. You can always explicitly use std::mutex if you have shared raw_ostreams.> > > Of course, one might wonder why someone would need to output to a stream > from multiple threads at the same time. > > > > But imagine someone might get logs to dbgs() or errs() running the > backend for a target in multiple threads. > > These are unbuffered, I wouldn’t expect a race in the code you list above. > I believe it’ll always forward directly to raw_fd_ostream::write_impl(), > which is calling the libc ::write(). > > — > Mehdi > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161207/dbd09d6a/attachment.html>
Maybe Matching Threads
- Race condition in raw_ostream
- Race condition in raw_ostream
- [LLVMdev] SmallString + raw_svector_ostream combination should be more efficient
- [LLVMdev] SmallString + raw_svector_ostream combination should be more efficient
- [LLVMdev] SmallString + raw_svector_ostream combination should be more efficient