Skip to content

Commit 9609f57

Browse files
committed
8361752: Double free in CompileQueue::delete_all after JDK-8357473
Reviewed-by: kvn, vlivanov
1 parent 441dbde commit 9609f57

File tree

5 files changed

+31
-52
lines changed

5 files changed

+31
-52
lines changed

src/hotspot/share/compiler/compileBroker.cpp

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -367,33 +367,31 @@ void CompileQueue::add(CompileTask* task) {
367367
*/
368368
void CompileQueue::delete_all() {
369369
MutexLocker mu(MethodCompileQueue_lock);
370-
CompileTask* next = _first;
370+
CompileTask* current = _first;
371371

372372
// Iterate over all tasks in the compile queue
373-
while (next != nullptr) {
374-
CompileTask* current = next;
375-
next = current->next();
376-
bool found_waiter = false;
377-
{
378-
MutexLocker ct_lock(CompileTaskWait_lock);
379-
assert(current->waiting_for_completion_count() <= 1, "more than one thread are waiting for task");
380-
if (current->waiting_for_completion_count() > 0) {
381-
// If another thread waits for this task, we must wake them up
382-
// so they will stop waiting and free the task.
383-
CompileTaskWait_lock->notify_all();
384-
found_waiter = true;
385-
}
386-
}
387-
if (!found_waiter) {
388-
// If no one was waiting for this task, we need to delete it ourselves.
389-
// In this case, the task is also certainly unlocked, because, again, there is no waiter.
390-
// Otherwise, by convention, it's the waiters responsibility to delete the task.
373+
while (current != nullptr) {
374+
if (!current->is_blocking()) {
375+
// Non-blocking task. No one is waiting for it, delete it now.
391376
delete current;
377+
} else {
378+
// Blocking task. By convention, it is the waiters responsibility
379+
// to delete the task. We cannot delete it here, because we do not
380+
// coordinate with waiters. We will notify the waiters later.
392381
}
382+
current = current->next();
393383
}
394384
_first = nullptr;
395385
_last = nullptr;
396386

387+
// Wake up all blocking task waiters to deal with remaining blocking
388+
// tasks. This is not a performance sensitive path, so we do this
389+
// unconditionally to simplify coding/testing.
390+
{
391+
MonitorLocker ml(Thread::current(), CompileTaskWait_lock);
392+
ml.notify_all();
393+
}
394+
397395
// Wake up all threads that block on the queue.
398396
MethodCompileQueue_lock->notify_all();
399397
}
@@ -1720,23 +1718,26 @@ void CompileBroker::wait_for_completion(CompileTask* task) {
17201718
} else
17211719
#endif
17221720
{
1723-
MonitorLocker ml(thread, CompileTaskWait_lock);
17241721
free_task = true;
1725-
task->inc_waiting_for_completion();
1722+
// Wait until the task is complete or compilation is shut down.
1723+
MonitorLocker ml(thread, CompileTaskWait_lock);
17261724
while (!task->is_complete() && !is_compilation_disabled_forever()) {
17271725
ml.wait();
17281726
}
1729-
task->dec_waiting_for_completion();
17301727
}
17311728

1732-
if (free_task) {
1733-
if (is_compilation_disabled_forever()) {
1734-
delete task;
1735-
return;
1736-
}
1729+
// It is harmless to check this status without the lock, because
1730+
// completion is a stable property.
1731+
if (!task->is_complete() && is_compilation_disabled_forever()) {
1732+
// Task is not complete, and we are exiting for compilation shutdown.
1733+
// The task can still be executed by some compiler thread, therefore
1734+
// we cannot delete it. This will leave task allocated, which leaks it.
1735+
// At this (degraded) point, it is less risky to abandon the task,
1736+
// rather than attempting a more complicated deletion protocol.
1737+
free_task = false;
1738+
}
17371739

1738-
// It is harmless to check this status without the lock, because
1739-
// completion is a stable property (until the task object is deleted).
1740+
if (free_task) {
17401741
assert(task->is_complete(), "Compilation should have completed");
17411742

17421743
// By convention, the waiter is responsible for deleting a

src/hotspot/share/compiler/compileBroker.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ class CompileBroker: AllStatic {
381381
}
382382

383383
static bool is_compilation_disabled_forever() {
384-
return _should_compile_new_jobs == shutdown_compilation;
384+
return Atomic::load(&_should_compile_new_jobs) == shutdown_compilation;
385385
}
386386

387387
static void wait_for_no_active_tasks();

src/hotspot/share/compiler/compileTask.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ CompileTask::CompileTask(int compile_id,
5656
_comp_level = comp_level;
5757
_num_inlined_bytecodes = 0;
5858

59-
_waiting_count = 0;
60-
6159
_is_complete = false;
6260
_is_success = false;
6361

src/hotspot/share/compiler/compileTask.hpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ class CompileTask : public CHeapObj<mtCompiler> {
9999
// Compilation state for a blocking JVMCI compilation
100100
JVMCICompileState* _blocking_jvmci_compile_state;
101101
#endif
102-
int _waiting_count; // See waiting_for_completion_count()
103102
int _comp_level;
104103
int _num_inlined_bytecodes;
105104
CompileTask* _next, *_prev;
@@ -164,23 +163,6 @@ class CompileTask : public CHeapObj<mtCompiler> {
164163
}
165164
#endif
166165

167-
// See how many threads are waiting for this task. Must have lock to read this.
168-
int waiting_for_completion_count() {
169-
assert(CompileTaskWait_lock->owned_by_self(), "must have lock to use waiting_for_completion_count()");
170-
return _waiting_count;
171-
}
172-
// Indicates that a thread is waiting for this task to complete. Must have lock to use this.
173-
void inc_waiting_for_completion() {
174-
assert(CompileTaskWait_lock->owned_by_self(), "must have lock to use inc_waiting_for_completion()");
175-
_waiting_count++;
176-
}
177-
// Indicates that a thread stopped waiting for this task to complete. Must have lock to use this.
178-
void dec_waiting_for_completion() {
179-
assert(CompileTaskWait_lock->owned_by_self(), "must have lock to use dec_waiting_for_completion()");
180-
assert(_waiting_count > 0, "waiting count is not positive");
181-
_waiting_count--;
182-
}
183-
184166
void mark_complete() { _is_complete = true; }
185167
void mark_success() { _is_success = true; }
186168
void mark_started(jlong time) { _time_started = time; }

test/hotspot/jtreg/ProblemList.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ compiler/c2/TestVerifyConstraintCasts.java 8355574 generic-all
8282

8383
compiler/c2/aarch64/TestStaticCallStub.java 8359963 linux-aarch64,macosx-aarch64
8484

85-
compiler/debug/TestStressBailout.java 8361752 generic-all
86-
8785
#############################################################################
8886

8987
# :hotspot_gc

0 commit comments

Comments
 (0)