Ensure we use a MPMC queue in ThreadDeathWatcher as it may be used from multiple threads at the same time.
Motivation: We used a MPSC queue in ThreadDeathWatcher and checked if it empty via isEmpty() from multiple threads if very unlucky. Depending on the implementation this is not safe and may even produce things like live-locks. Modifications: Change to use a MPMC queue. Result: No more risk to run into issues when multiple threads call watch(...) / unwatch(...) concurrently.
This commit is contained in:
parent
3d11334151
commit
28c39a3183
@ -17,7 +17,6 @@
|
|||||||
package io.netty.util;
|
package io.netty.util;
|
||||||
|
|
||||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
import io.netty.util.internal.SystemPropertyUtil;
|
import io.netty.util.internal.SystemPropertyUtil;
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
@ -26,6 +25,7 @@ import io.netty.util.internal.logging.InternalLoggerFactory;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -44,7 +44,9 @@ public final class ThreadDeathWatcher {
|
|||||||
// visible for testing
|
// visible for testing
|
||||||
static final ThreadFactory threadFactory;
|
static final ThreadFactory threadFactory;
|
||||||
|
|
||||||
private static final Queue<Entry> pendingEntries = PlatformDependent.newMpscQueue();
|
// Use a MPMC queue as we may end up checking isEmpty() from multiple threads which may not be allowed to do
|
||||||
|
// concurrently depending on the implemenation of it in a MPSC queue.
|
||||||
|
private static final Queue<Entry> pendingEntries = new ConcurrentLinkedQueue<Entry>();
|
||||||
private static final Watcher watcher = new Watcher();
|
private static final Watcher watcher = new Watcher();
|
||||||
private static final AtomicBoolean started = new AtomicBoolean();
|
private static final AtomicBoolean started = new AtomicBoolean();
|
||||||
private static volatile Thread watcherThread;
|
private static volatile Thread watcherThread;
|
||||||
|
Loading…
Reference in New Issue
Block a user