8202303: LogStream should autoflush on destruction
authorstuefe
Thu, 03 May 2018 07:35:17 +0200
changeset 49961 7379e6f906ae
parent 49960 3ab6ba9f94a9
child 49962 3b43e97b3697
child 56508 f67f588ebf15
8202303: LogStream should autoflush on destruction Reviewed-by: dholmes, rehn, zgu
src/hotspot/share/logging/logStream.cpp
src/hotspot/share/logging/logStream.hpp
test/hotspot/gtest/logging/test_logStream.cpp
--- 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"));
+}
+