8268165: AsyncLogging will crash if rotate() fails

LogFileOutput::rotate() may leave _stream NULL because os::fopen() may return NULL due to space or inode limitations.  AsyncLogWriter::write() calls LogFileOutput::write_blocking() without null check.  Null check is added to prevent from crashing.

Reviewed-by: ysuenaga
This commit is contained in:
Xin Liu 2021-06-08 07:20:13 +00:00 committed by Yasumasa Suenaga
parent fd91b2aa57
commit 81054789a3

View File

@ -285,8 +285,26 @@ bool LogFileOutput::initialize(const char* options, outputStream* errstream) {
return true;
}
class RotationLocker : public StackObj {
Semaphore& _sem;
public:
RotationLocker(Semaphore& sem) : _sem(sem) {
sem.wait();
}
~RotationLocker() {
_sem.signal();
}
};
int LogFileOutput::write_blocking(const LogDecorations& decorations, const char* msg) {
_rotation_semaphore.wait();
RotationLocker lock(_rotation_semaphore);
if (_stream == NULL) {
// An error has occurred with this output, avoid writing to it.
return 0;
}
int written = LogFileStreamOutput::write(decorations, msg);
if (written > 0) {
_current_size += written;
@ -295,7 +313,6 @@ int LogFileOutput::write_blocking(const LogDecorations& decorations, const char*
rotate();
}
}
_rotation_semaphore.signal();
return written;
}
@ -327,7 +344,7 @@ int LogFileOutput::write(LogMessageBuffer::Iterator msg_iterator) {
return 0;
}
_rotation_semaphore.wait();
RotationLocker lock(_rotation_semaphore);
int written = LogFileStreamOutput::write(msg_iterator);
if (written > 0) {
_current_size += written;
@ -336,7 +353,6 @@ int LogFileOutput::write(LogMessageBuffer::Iterator msg_iterator) {
rotate();
}
}
_rotation_semaphore.signal();
return written;
}
@ -363,13 +379,12 @@ void LogFileOutput::force_rotate() {
// Rotation not possible
return;
}
_rotation_semaphore.wait();
RotationLocker lock(_rotation_semaphore);
rotate();
_rotation_semaphore.signal();
}
void LogFileOutput::rotate() {
if (fclose(_stream)) {
jio_fprintf(defaultStream::error_stream(), "Error closing file '%s' during log rotation (%s).\n",
_file_name, os::strerror(errno));