8202303: LogStream should autoflush on destruction
Reviewed-by: dholmes, rehn, zgu
--- a/src/hotspot/share/logging/logStream.cpp Wed May 02 18:36:49 2018 -0700
+++ b/src/hotspot/share/logging/logStream.cpp Thu May 03 07:35:17 2018 +0200
@@ -112,3 +112,12 @@
update_position(s, len);
}
+// Destructor writes any unfinished output left in the line buffer.
+LogStream::~LogStream() {
+ if (_current_line.is_empty() == false) {
+ _log_handle.print("%s", _current_line.buffer());
+ _current_line.reset();
+ }
+}
+
+
--- a/src/hotspot/share/logging/logStream.hpp Wed May 02 18:36:49 2018 -0700
+++ b/src/hotspot/share/logging/logStream.hpp Thu May 03 07:35:17 2018 +0200
@@ -48,6 +48,7 @@
public:
LineBuffer();
~LineBuffer();
+ bool is_empty() const { return _pos == 0; }
const char* buffer() const { return _buf; }
void append(const char* s, size_t len);
void reset();
@@ -77,6 +78,9 @@
LogStream(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>* type_carrier) :
_log_handle(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
+ // Destructor writes any unfinished output left in the line buffer.
+ ~LogStream();
+
// Constructor to support creation from a LogTargetHandle.
//
// LogTarget(Debug, gc) log;
--- a/test/hotspot/gtest/logging/test_logStream.cpp Wed May 02 18:36:49 2018 -0700
+++ b/test/hotspot/gtest/logging/test_logStream.cpp Thu May 03 07:35:17 2018 +0200
@@ -71,8 +71,10 @@
const int max_line_len = 1024;
char* const test_string = (char*) os::malloc(max_line_len, mtLogging);
memset(test_string, 'A', max_line_len);
+ Log(gc) log;
+ set_log_config(TestLogFileName, "gc=debug");
for (int interval = 1; interval < max_line_len; interval++) {
- LogStream ls(Log(logging)::info());
+ LogStream ls(log.debug());
int written = 0;
while (written < max_line_len) {
const int to_write = MIN2(interval, max_line_len - written);
@@ -84,7 +86,6 @@
}
ASSERT_TRUE(line_buffer[written] == '\0');
}
- ls.cr(); // I do not expect printout, nor do I care. Just call cr() to flush and avoid assert in ~LogStream().
}
}
@@ -100,3 +101,14 @@
// reset to prevent assert for unflushed content
ls._current_line.reset();
}
+
+TEST_VM_F(LogStreamTest, autoflush_on_destruction) {
+ Log(gc) log;
+ set_log_config(TestLogFileName, "gc=debug");
+ {
+ LogStream stream(log.debug());
+ stream.print("ABCD"); // Unfinished line. I expect not to assert upon leaving the scope.
+ }
+ EXPECT_TRUE(file_contains_substring(TestLogFileName, "ABCD\n"));
+}
+