mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-15 13:49:42 +02:00
8364501: Compiler shutdown crashes on access to deleted CompileTask
Reviewed-by: kvn, mhaessig
This commit is contained in:
parent
e9e331b2a9
commit
958383d69c
3 changed files with 18 additions and 8 deletions
|
@ -371,6 +371,7 @@ void CompileQueue::delete_all() {
|
|||
|
||||
// Iterate over all tasks in the compile queue
|
||||
while (current != nullptr) {
|
||||
CompileTask* next = current->next();
|
||||
if (!current->is_blocking()) {
|
||||
// Non-blocking task. No one is waiting for it, delete it now.
|
||||
delete current;
|
||||
|
@ -379,7 +380,7 @@ void CompileQueue::delete_all() {
|
|||
// to delete the task. We cannot delete it here, because we do not
|
||||
// coordinate with waiters. We will notify the waiters later.
|
||||
}
|
||||
current = current->next();
|
||||
current = next;
|
||||
}
|
||||
_first = nullptr;
|
||||
_last = nullptr;
|
||||
|
@ -504,6 +505,8 @@ void CompileQueue::remove(CompileTask* task) {
|
|||
assert(task == _last, "Sanity");
|
||||
_last = task->prev();
|
||||
}
|
||||
task->set_next(nullptr);
|
||||
task->set_prev(nullptr);
|
||||
--_size;
|
||||
++_total_removed;
|
||||
}
|
||||
|
@ -1728,17 +1731,22 @@ void CompileBroker::wait_for_completion(CompileTask* task) {
|
|||
|
||||
// It is harmless to check this status without the lock, because
|
||||
// completion is a stable property.
|
||||
if (!task->is_complete() && is_compilation_disabled_forever()) {
|
||||
// Task is not complete, and we are exiting for compilation shutdown.
|
||||
// The task can still be executed by some compiler thread, therefore
|
||||
// we cannot delete it. This will leave task allocated, which leaks it.
|
||||
// At this (degraded) point, it is less risky to abandon the task,
|
||||
// rather than attempting a more complicated deletion protocol.
|
||||
if (!task->is_complete()) {
|
||||
// Task is not complete, likely because we are exiting for compilation
|
||||
// shutdown. The task can still be reached through the queue, or executed
|
||||
// by some compiler thread. There is no coordination with either MCQ lock
|
||||
// holders or compilers, therefore we cannot delete the task.
|
||||
//
|
||||
// This will leave task allocated, which leaks it. At this (degraded) point,
|
||||
// it is less risky to abandon the task, rather than attempting a more
|
||||
// complicated deletion protocol.
|
||||
free_task = false;
|
||||
}
|
||||
|
||||
if (free_task) {
|
||||
assert(task->is_complete(), "Compilation should have completed");
|
||||
assert(task->next() == nullptr && task->prev() == nullptr,
|
||||
"Completed task should not be in the queue");
|
||||
|
||||
// By convention, the waiter is responsible for deleting a
|
||||
// blocking CompileTask. Since there is only one waiter ever
|
||||
|
|
|
@ -74,6 +74,7 @@ CompileTask::CompileTask(int compile_id,
|
|||
_arena_bytes = 0;
|
||||
|
||||
_next = nullptr;
|
||||
_prev = nullptr;
|
||||
|
||||
Atomic::add(&_active_tasks, 1, memory_order_relaxed);
|
||||
}
|
||||
|
|
|
@ -101,7 +101,8 @@ class CompileTask : public CHeapObj<mtCompiler> {
|
|||
#endif
|
||||
int _comp_level;
|
||||
int _num_inlined_bytecodes;
|
||||
CompileTask* _next, *_prev;
|
||||
CompileTask* _next;
|
||||
CompileTask* _prev;
|
||||
// Fields used for logging why the compilation was initiated:
|
||||
jlong _time_queued; // time when task was enqueued
|
||||
jlong _time_started; // time when compilation started
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue