Skip to content

Commit 9924c45

Browse files
hseigelMarkus Grönlund
authored and
Markus Grönlund
committedSep 1, 2020
8252090: JFR: StreamWriterHost::write_unbuffered() stucks in an infinite loop OpenJDK (build 13.0.1+9)
Reviewed-by: hseigel
1 parent 5ca47be commit 9924c45

10 files changed

+55
-36
lines changed
 

‎src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ static jlong add_method_info(JfrBigEndianWriter& writer,
625625
DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)
626626
// Code attribute
627627
writer.write(code_index); // "Code"
628-
writer.bytes(code, code_len);
628+
writer.write_bytes(code, code_len);
629629
DEBUG_ONLY(assert((start_offset + 8 + 2 + (jlong)code_len) == writer.current_offset(), "invariant");)
630630
return writer.current_offset();
631631
}
@@ -768,8 +768,8 @@ static u2 position_stream_after_methods(JfrBigEndianWriter& writer,
768768
// We will need to re-create a new <clinit> in a later step.
769769
// For now, ensure that this method is excluded from the methods
770770
// being copied.
771-
writer.bytes(stream->buffer() + orig_method_len_offset,
772-
method_offset - orig_method_len_offset);
771+
writer.write_bytes(stream->buffer() + orig_method_len_offset,
772+
method_offset - orig_method_len_offset);
773773
assert(writer.is_valid(), "invariant");
774774

775775
// Update copy position to skip copy of <clinit> method
@@ -1091,7 +1091,7 @@ static jlong insert_clinit_method(const InstanceKlass* ik,
10911091
writer.write<u1>((u1)Bytecodes::_nop);
10921092
writer.write<u1>((u1)Bytecodes::_nop);
10931093
// insert original clinit code
1094-
writer.bytes(orig_bytecodes, orig_bytecodes_length);
1094+
writer.write_bytes(orig_bytecodes, orig_bytecodes_length);
10951095
}
10961096

10971097
/* END CLINIT CODE */
@@ -1290,7 +1290,7 @@ static u1* new_bytes_for_lazy_instrumentation(const InstanceKlass* ik,
12901290
const u4 orig_access_flag_offset = orig_stream->current_offset();
12911291
// Copy original stream from the beginning up to AccessFlags
12921292
// This means the original constant pool contents are copied unmodified
1293-
writer.bytes(orig_stream->buffer(), orig_access_flag_offset);
1293+
writer.write_bytes(orig_stream->buffer(), orig_access_flag_offset);
12941294
assert(writer.is_valid(), "invariant");
12951295
assert(writer.current_offset() == (intptr_t)orig_access_flag_offset, "invariant"); // same positions
12961296
// Our writer now sits just after the last original constant pool entry.
@@ -1324,14 +1324,14 @@ static u1* new_bytes_for_lazy_instrumentation(const InstanceKlass* ik,
13241324
orig_stream->skip_u2_fast(iface_len);
13251325
const u4 orig_fields_len_offset = orig_stream->current_offset();
13261326
// Copy from AccessFlags up to and including interfaces
1327-
writer.bytes(orig_stream->buffer() + orig_access_flag_offset,
1328-
orig_fields_len_offset - orig_access_flag_offset);
1327+
writer.write_bytes(orig_stream->buffer() + orig_access_flag_offset,
1328+
orig_fields_len_offset - orig_access_flag_offset);
13291329
assert(writer.is_valid(), "invariant");
13301330
const jlong new_fields_len_offset = writer.current_offset();
13311331
const u2 orig_fields_len = position_stream_after_fields(orig_stream);
13321332
u4 orig_method_len_offset = orig_stream->current_offset();
13331333
// Copy up to and including fields
1334-
writer.bytes(orig_stream->buffer() + orig_fields_len_offset, orig_method_len_offset - orig_fields_len_offset);
1334+
writer.write_bytes(orig_stream->buffer() + orig_fields_len_offset, orig_method_len_offset - orig_fields_len_offset);
13351335
assert(writer.is_valid(), "invariant");
13361336
// We are sitting just after the original number of field_infos
13371337
// so this is a position where we can add (append) new field_infos
@@ -1350,7 +1350,7 @@ static u1* new_bytes_for_lazy_instrumentation(const InstanceKlass* ik,
13501350
orig_method_len_offset);
13511351
const u4 orig_attributes_count_offset = orig_stream->current_offset();
13521352
// Copy existing methods
1353-
writer.bytes(orig_stream->buffer() + orig_method_len_offset, orig_attributes_count_offset - orig_method_len_offset);
1353+
writer.write_bytes(orig_stream->buffer() + orig_method_len_offset, orig_attributes_count_offset - orig_method_len_offset);
13541354
assert(writer.is_valid(), "invariant");
13551355
// We are sitting just after the original number of method_infos
13561356
// so this is a position where we can add (append) new method_infos
@@ -1372,7 +1372,7 @@ static u1* new_bytes_for_lazy_instrumentation(const InstanceKlass* ik,
13721372
writer.write_at_offset<u2>(orig_methods_len + number_of_new_methods, new_method_len_offset);
13731373
assert(writer.is_valid(), "invariant");
13741374
// Copy last remaining bytes
1375-
writer.bytes(orig_stream->buffer() + orig_attributes_count_offset, orig_stream_size - orig_attributes_count_offset);
1375+
writer.write_bytes(orig_stream->buffer() + orig_attributes_count_offset, orig_stream_size - orig_attributes_count_offset);
13761376
assert(writer.is_valid(), "invariant");
13771377
assert(writer.current_offset() > orig_stream->length(), "invariant");
13781378
size_of_new_bytes = (jint)writer.current_offset();

‎src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class JfrChunkHeadWriter : public StackObj {
6262
JfrChunk* _chunk;
6363
public:
6464
void write_magic() {
65-
_writer->bytes(_chunk->magic(), MAGIC_LEN);
65+
_writer->write_bytes(_chunk->magic(), MAGIC_LEN);
6666
}
6767

6868
void write_version() {

‎src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131

3232
template <typename T>
3333
inline bool UnBufferedWriteToChunk<T>::write(T* t, const u1* data, size_t size) {
34-
_writer.write_unbuffered(data, size);
34+
assert((intptr_t)size >= 0, "invariant");
35+
_writer.write_unbuffered(data, (intptr_t)size);
3536
++_elements;
3637
_size += size;
3738
return true;
@@ -56,6 +57,7 @@ inline bool ConcurrentWriteOp<Operation>::process(typename Operation::Type* t) {
5657
// acquire_critical_section_top() must be read before pos() for stable access
5758
const u1* const top = is_retired ? t->top() : t->acquire_critical_section_top();
5859
const size_t unflushed_size = get_unflushed_size(top, t);
60+
assert((intptr_t)unflushed_size >= 0, "invariant");
5961
if (unflushed_size == 0) {
6062
if (is_retired) {
6163
t->set_top(top);
@@ -78,6 +80,7 @@ inline bool MutexedWriteOp<Operation>::process(typename Operation::Type* t) {
7880
assert(t != NULL, "invariant");
7981
const u1* const top = t->top();
8082
const size_t unflushed_size = get_unflushed_size(top, t);
83+
assert((intptr_t)unflushed_size >= 0, "invariant");
8184
if (unflushed_size == 0) {
8285
return true;
8386
}
@@ -113,6 +116,7 @@ inline bool DiscardOp<Operation>::process(typename Operation::Type* t) {
113116
assert(t != NULL, "invariant");
114117
const u1* const top = _mode == concurrent ? t->acquire_critical_section_top() : t->top();
115118
const size_t unflushed_size = get_unflushed_size(top, t);
119+
assert((intptr_t)unflushed_size >= 0, "invariant");
116120
if (unflushed_size == 0) {
117121
if (_mode == concurrent) {
118122
t->release_critical_section_top(top);
@@ -141,6 +145,7 @@ inline bool EpochDispatchOp<Operation>::process(typename Operation::Type* t) {
141145
assert(t != NULL, "invariant");
142146
const u1* const current_top = _previous_epoch ? t->start() : t->top();
143147
const size_t unflushed_size = Atomic::load_acquire(t->pos_address()) - current_top;
148+
assert((intptr_t)unflushed_size >= 0, "invariant");
144149
if (unflushed_size == 0) {
145150
return true;
146151
}

‎src/hotspot/share/jfr/utilities/jfrBlob.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class JfrBlob : public JfrCHeapObj {
5050
static JfrBlobHandle make(const u1* data, size_t size);
5151
template <typename Writer>
5252
void write(Writer& writer) const {
53-
writer.bytes(_data, _size);
53+
writer.write_bytes(_data, _size);
5454
if (_next.valid()) {
5555
_next->write(writer);
5656
}
@@ -60,7 +60,7 @@ class JfrBlob : public JfrCHeapObj {
6060
if (_written) {
6161
return;
6262
}
63-
writer.bytes(_data, _size);
63+
writer.write_bytes(_data, _size);
6464
_written = true;
6565
if (_next.valid()) {
6666
_next->exclusive_write(writer);

‎src/hotspot/share/jfr/writers/jfrMemoryWriterHost.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class MemoryWriterHost : public StorageHost<Adapter, AP> {
4949
public:
5050
typedef typename Adapter::StorageType StorageType;
5151
protected:
52-
void bytes(void* dest, const void* buf, size_t len);
52+
void write_bytes(void* dest, const void* buf, intptr_t len);
5353
MemoryWriterHost(StorageType* storage, Thread* thread);
5454
MemoryWriterHost(StorageType* storage, size_t size);
5555
MemoryWriterHost(Thread* thread);

‎src/hotspot/share/jfr/writers/jfrMemoryWriterHost.inline.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
#include "jfr/writers/jfrMemoryWriterHost.hpp"
2929

3030
template <typename Adapter, typename AP, typename AccessAssert>
31-
inline void MemoryWriterHost<Adapter, AP, AccessAssert>::bytes(void* dest, const void* buf, size_t len) {
31+
inline void MemoryWriterHost<Adapter, AP, AccessAssert>::write_bytes(void* dest, const void* buf, intptr_t len) {
3232
assert(dest != NULL, "invariant");
33-
memcpy(dest, buf, len); // no encoding
33+
assert(len >= 0, "invariant");
34+
memcpy(dest, buf, (size_t)len); // no encoding
3435
this->set_current_pos(len);
3536
}
3637

‎src/hotspot/share/jfr/writers/jfrStreamWriterHost.hpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -37,20 +37,22 @@ class StreamWriterHost : public MemoryWriterHost<Adapter, AP> {
3737
fio_fd _fd;
3838
int64_t current_stream_position() const;
3939

40+
void write_bytes(const u1* buf, intptr_t len);
41+
4042
protected:
4143
StreamWriterHost(StorageType* storage, Thread* thread);
4244
StreamWriterHost(StorageType* storage, size_t size);
4345
StreamWriterHost(Thread* thread);
4446
bool accommodate(size_t used, size_t requested);
45-
void bytes(void* dest, const void* src, size_t len);
47+
void write_bytes(void* dest, const void* src, intptr_t len);
4648
void flush(size_t size);
4749
bool has_valid_fd() const;
4850

4951
public:
5052
int64_t current_offset() const;
5153
void seek(int64_t offset);
5254
void flush();
53-
void write_unbuffered(const void* src, size_t len);
55+
void write_unbuffered(const void* src, intptr_t len);
5456
bool is_valid() const;
5557
void close_fd();
5658
void reset(fio_fd fd);

‎src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp

+21-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -61,19 +61,33 @@ inline bool StreamWriterHost<Adapter, AP>::accommodate(size_t used, size_t reque
6161
}
6262

6363
template <typename Adapter, typename AP>
64-
inline void StreamWriterHost<Adapter, AP>::bytes(void* dest, const void* buf, size_t len) {
65-
if (len > this->available_size()) {
64+
inline void StreamWriterHost<Adapter, AP>::write_bytes(void* dest, const void* buf, intptr_t len) {
65+
assert(len >= 0, "invariant");
66+
if (len > (intptr_t)this->available_size()) {
6667
this->write_unbuffered(buf, len);
6768
return;
6869
}
69-
MemoryWriterHost<Adapter, AP>::bytes(dest, buf, len);
70+
MemoryWriterHost<Adapter, AP>::write_bytes(dest, buf, len);
71+
}
72+
73+
template <typename Adapter, typename AP>
74+
inline void StreamWriterHost<Adapter, AP>::write_bytes(const u1* buf, intptr_t len) {
75+
assert(len >= 0, "invariant");
76+
while (len > 0) {
77+
const unsigned int nBytes = len > INT_MAX ? INT_MAX : (unsigned int)len;
78+
const ssize_t num_written = (ssize_t)os::write(_fd, buf, nBytes);
79+
guarantee(num_written > 0, "Nothing got written, or os::write() failed");
80+
_stream_pos += num_written;
81+
len -= num_written;
82+
buf += num_written;
83+
}
7084
}
7185

7286
template <typename Adapter, typename AP>
7387
inline void StreamWriterHost<Adapter, AP>::flush(size_t size) {
7488
assert(size > 0, "invariant");
7589
assert(this->is_valid(), "invariant");
76-
_stream_pos += os::write(_fd, this->start_pos(), (unsigned int)size);
90+
this->write_bytes(this->start_pos(), (intptr_t)size);
7791
StorageHost<Adapter, AP>::reset();
7892
assert(0 == this->used_offset(), "invariant");
7993
}
@@ -106,14 +120,10 @@ void StreamWriterHost<Adapter, AP>::flush() {
106120
}
107121

108122
template <typename Adapter, typename AP>
109-
void StreamWriterHost<Adapter, AP>::write_unbuffered(const void* buf, size_t len) {
123+
void StreamWriterHost<Adapter, AP>::write_unbuffered(const void* buf, intptr_t len) {
110124
this->flush();
111125
assert(0 == this->used_offset(), "can only seek from beginning");
112-
while (len > 0) {
113-
const unsigned int n = MIN2((unsigned int)len, (unsigned int)INT_MAX);
114-
_stream_pos += os::write(_fd, buf, n);
115-
len -= n;
116-
}
126+
this->write_bytes((const u1*)buf, len);
117127
}
118128

119129
template <typename Adapter, typename AP>

‎src/hotspot/share/jfr/writers/jfrWriterHost.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -88,7 +88,7 @@ class WriterHost : public WriterPolicyImpl {
8888
void write(const Tickspan& time);
8989
void write(const JfrTicks& time);
9090
void write(const JfrTickspan& time);
91-
void bytes(const void* buf, size_t len);
91+
void write_bytes(const void* buf, intptr_t len);
9292
void write_utf8_u2_len(const char* value);
9393
template <typename T>
9494
void write_padded_at_offset(T value, int64_t offset);

‎src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,11 @@ void WriterHost<BE, IE, WriterPolicyImpl>::write(const JfrTickspan& time) {
293293
}
294294

295295
template <typename BE, typename IE, typename WriterPolicyImpl>
296-
void WriterHost<BE, IE, WriterPolicyImpl>::bytes(const void* buf, size_t len) {
297-
u1* const pos = this->ensure_size(len);
296+
void WriterHost<BE, IE, WriterPolicyImpl>::write_bytes(const void* buf, intptr_t len) {
297+
assert(len >= 0, "invariant");
298+
u1* const pos = this->ensure_size((size_t)len);
298299
if (pos != NULL) {
299-
WriterPolicyImpl::bytes(pos, buf, len); // WriterPolicyImpl responsible for position update
300+
WriterPolicyImpl::write_bytes(pos, buf, len); // WriterPolicyImpl responsible for position update
300301
}
301302
}
302303

0 commit comments

Comments
 (0)
Please sign in to comment.