New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test/log: fix for crash with libc++ #20233
Conversation
the original issue reproduced with operator<<(const char*) in libstdc++, but this actually crashes with libc++. test the std::basic_streambuf* overload instead, which is called out explicitly in http://en.cppreference.com/w/cpp/io/ios_base/iostate: > The badbit is set by the following standard library functions: > * basic_ostream::operator<<(basic_streambuf*) when a null pointer is passed as the argument. Signed-off-by: Casey Bodley <cbodley@redhat.com>
@@ -59,7 +59,7 @@ TEST(Log, ReuseBad) | |||
{ | |||
auto e = log.create_entry(l, 1); | |||
auto& out = e->get_ostream(); | |||
out << (const char*)nullptr; | |||
out << (std::streambuf*)nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cbodley after a second thought, i feel that we are covering potential bugs. if we fail to print a logging message because of the badbit set by previous logging message printed using this TLS stream instance, it is a sign that we have a programming error when printing logging messages. because we should not print a (std::streambuf*)nullptr
, should we?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the person who noticed this bug, and having thought about this line of reasoning, I'd prefer that we reset the stream. The fact that in libstdc++ environments "nothing happens" other than recoverable stream failure after sending the nullptr, means that attention may not be drawn to a future case where we send bad data. If a case does slip in, the stream reset makes it easier to find, as well as remediating the damage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance cost of the reset would be a strong reason not to do it, though. I suspect that's not an issue though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattbenjamin badbit denotes irrecoverable error. so all following logging messages won't be printed. so i guess it'd be relatively easy to track back to the offending log line which was not printed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattbenjamin @tchaikov
Without clear() on stream:
[ RUN ] Log.Speed_gather
[ OK ] Log.Speed_gather (1222 ms)
[ RUN ] Log.Speed_nogather
[ OK ] Log.Speed_nogather (46 ms)
With clear() on stream:
[ RUN ] Log.Speed_gather
[ OK ] Log.Speed_gather (1247 ms)
[ RUN ] Log.Speed_nogather
[ OK ] Log.Speed_nogather (45 ms)
Before TLS optimizations:
[ RUN ] Log.Speed_gather
[ OK ] Log.Speed_gather (1636 ms)
[ RUN ] Log.Speed_nogather
[ OK ] Log.Speed_nogather (49 ms)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aclamk thank you for profiling this change. i don't feel strong either way then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i still think that we need to find out the offending log line and then drop this fix.
the original issue reproduced with operator<<(const char*) in libstdc++, but this actually crashes with libc++. test the std::basic_streambuf* overload instead, which is called out explicitly in http://en.cppreference.com/w/cpp/io/ios_base/iostate: