Fix an unexpected RejectedExecutionException
- Ensure to run all remaining tasks before marking the executor as 'shut down'.
This commit is contained in:
parent
3393629eed
commit
660e4548a6
@ -90,13 +90,19 @@ public abstract class SingleThreadEventExecutor extends AbstractExecutorService
|
||||
CURRENT_EVENT_LOOP.set(SingleThreadEventExecutor.this);
|
||||
try {
|
||||
SingleThreadEventExecutor.this.run();
|
||||
} finally {
|
||||
try {
|
||||
// Run all remaining tasks and shutdown hooks.
|
||||
try {
|
||||
cleanupTasks();
|
||||
} finally {
|
||||
synchronized (stateLock) {
|
||||
state = 3;
|
||||
}
|
||||
}
|
||||
cleanupTasks();
|
||||
} finally {
|
||||
try {
|
||||
cancelScheduledTasks();
|
||||
runShutdownHooks();
|
||||
cleanup();
|
||||
} finally {
|
||||
threadLock.release();
|
||||
@ -104,6 +110,19 @@ public abstract class SingleThreadEventExecutor extends AbstractExecutorService
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupTasks() {
|
||||
for (;;) {
|
||||
boolean ran = false;
|
||||
cancelScheduledTasks();
|
||||
ran |= runAllTasks();
|
||||
ran |= runShutdownHooks();
|
||||
if (!ran && !hasTasks()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -196,16 +215,23 @@ public abstract class SingleThreadEventExecutor extends AbstractExecutorService
|
||||
return taskQueue.remove(task);
|
||||
}
|
||||
|
||||
protected void runAllTasks() {
|
||||
protected boolean runAllTasks() {
|
||||
boolean ran = false;
|
||||
for (;;) {
|
||||
final Runnable task = pollTask();
|
||||
if (task == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
task.run();
|
||||
ran = true;
|
||||
} catch (Throwable t) {
|
||||
logger.warn("A task raised an exception.", t);
|
||||
}
|
||||
}
|
||||
return ran;
|
||||
}
|
||||
|
||||
protected abstract void run();
|
||||
|
||||
@ -251,7 +277,8 @@ public abstract class SingleThreadEventExecutor extends AbstractExecutorService
|
||||
}
|
||||
}
|
||||
|
||||
private void runShutdownHooks() {
|
||||
private boolean runShutdownHooks() {
|
||||
boolean ran = false;
|
||||
// Note shutdown hooks can add / remove shutdown hooks.
|
||||
while (!shutdownHooks.isEmpty()) {
|
||||
List<Runnable> copy = new ArrayList<Runnable>(shutdownHooks);
|
||||
@ -259,11 +286,13 @@ public abstract class SingleThreadEventExecutor extends AbstractExecutorService
|
||||
for (Runnable task: copy) {
|
||||
try {
|
||||
task.run();
|
||||
ran = true;
|
||||
} catch (Throwable t) {
|
||||
logger.warn("Shutdown hook raised an exception.", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ran;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -358,7 +387,7 @@ public abstract class SingleThreadEventExecutor extends AbstractExecutorService
|
||||
}
|
||||
|
||||
private static void reject() {
|
||||
throw new RejectedExecutionException("event loop shut down");
|
||||
throw new RejectedExecutionException("event executor shut down");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user