Skip to content

Commit a85a723

Browse files
committed
8292351: tty should always live
Reviewed-by: clanger, coleenp, dholmes
1 parent 4da1745 commit a85a723

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

src/hotspot/share/utilities/ostream.cpp

+21-7
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,19 @@ stringStream::~stringStream() {
421421
}
422422
}
423423

424+
// tty needs to be always accessible since there are code paths that may write to it
425+
// outside of the VM lifespan.
426+
// Examples for pre-VM-init accesses: Early NMT init, Early UL init
427+
// Examples for post-VM-exit accesses: many, e.g. NMT C-heap bounds checker, signal handling, AGCT, ...
428+
// During lifetime tty is served by an instance of defaultStream. That instance's deletion cannot
429+
// be (easily) postponed or omitted since it has ties to the JVM infrastructure.
430+
// The policy followed here is a compromise reached during review of JDK-8292351:
431+
// - pre-init: we silently swallow all output. We won't see anything, but at least won't crash
432+
// - post-exit: we write to a simple fdStream, but somewhat mimic the behavior of the real defaultStream
433+
static nullStream tty_preinit_stream;
434+
outputStream* tty = &tty_preinit_stream;
435+
424436
xmlStream* xtty;
425-
outputStream* tty;
426437
extern Mutex* tty_lock;
427438

428439
#define EXTRACHARLEN 32
@@ -615,6 +626,9 @@ void fileStream::flush() {
615626
}
616627
}
617628

629+
fdStream fdStream::_stdout_stream(1);
630+
fdStream fdStream::_stderr_stream(2);
631+
618632
void fdStream::write(const char* s, size_t len) {
619633
if (_fd != -1) {
620634
// Make an unused local variable to avoid warning from gcc compiler.
@@ -961,13 +975,13 @@ void ostream_exit() {
961975
if (ostream_exit_called) return;
962976
ostream_exit_called = true;
963977
ClassListWriter::delete_classlist();
964-
if (tty != defaultStream::instance) {
965-
delete tty;
966-
}
967-
if (defaultStream::instance != NULL) {
968-
delete defaultStream::instance;
978+
// Make sure tty works after VM exit by assigning an always-on functioning fdStream.
979+
outputStream* tmp = tty;
980+
tty = DisplayVMOutputToStderr ? fdStream::stdout_stream() : fdStream::stderr_stream();
981+
if (tmp != &tty_preinit_stream && tmp != defaultStream::instance) {
982+
delete tmp;
969983
}
970-
tty = NULL;
984+
delete defaultStream::instance;
971985
xtty = NULL;
972986
defaultStream::instance = NULL;
973987
}

src/hotspot/share/utilities/ostream.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,26 @@ class fileStream : public outputStream {
248248
class fdStream : public outputStream {
249249
protected:
250250
int _fd;
251+
static fdStream _stdout_stream;
252+
static fdStream _stderr_stream;
251253
public:
252254
fdStream(int fd = -1) : _fd(fd) { }
253255
bool is_open() const { return _fd != -1; }
254256
void set_fd(int fd) { _fd = fd; }
255257
int fd() const { return _fd; }
256258
virtual void write(const char* c, size_t len);
257259
void flush() {};
260+
261+
// predefined streams for unbuffered IO to stdout, stderr
262+
static fdStream* stdout_stream() { return &_stdout_stream; }
263+
static fdStream* stderr_stream() { return &_stderr_stream; }
264+
};
265+
266+
// A /dev/null equivalent stream
267+
class nullStream : public outputStream {
268+
public:
269+
void write(const char* c, size_t len) {}
270+
void flush() {};
258271
};
259272

260273
void ostream_init();

0 commit comments

Comments
 (0)