Details
-
Bug
-
Resolution: Cannot Reproduce
-
P4
-
None
-
11
-
x86_64
-
linux
Description
A DESCRIPTION OF THE PROBLEM :
If you interrupt a thread that is opening a DatagramChannel, it sometimes deadlocks.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
On one thread, open a DatagramChannel, send a packet, and close the channel.
On a second thread, interrupt the first thread.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
First thread is interrupted successfully and aborts its blocking operations in a timely manner, likely throwing an InterruptedException
No deadlocks occur
ACTUAL -
Deadlock occurs sometimes.
Found one Java-level deadlock:
=============================
"main":
waiting to lock monitor 0x00007ff5d0006980 (object 0x00000006294856e8, a java.lang.Object),
which is held by "pool-1-thread-1"
"pool-1-thread-1":
waiting to lock monitor 0x00007ff5d0008b80 (object 0x00000006281ddf18, a java.lang.Object),
which is held by "main"
Java stack information for the threads listed above:
===================================================
"main":
at sun.nio.ch.DatagramChannelImpl.implCloseSelectableChannel(java.base@12.0.1/DatagramChannelImpl.java:1149)
- waiting to lock <0x00000006294856e8> (a java.lang.Object)
at java.nio.channels.spi.AbstractSelectableChannel.implCloseChannel(java.base@12.0.1/AbstractSelectableChannel.java:242)
at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(java.base@12.0.1/AbstractInterruptibleChannel.java:162)
- locked <0x0000000629485658> (a java.lang.Object)
at java.lang.Thread.interrupt(java.base@12.0.1/Thread.java:994)
- locked <0x00000006281ddf18> (a java.lang.Object)
"pool-1-thread-1":
at java.lang.Thread.blockedOn(java.base@12.0.1/Thread.java:238)
- waiting to lock <0x00000006281ddf18> (a java.lang.Object)
at java.lang.System$2.blockedOn(java.base@12.0.1/System.java:2173)
at java.nio.channels.spi.AbstractInterruptibleChannel.blockedOn(java.base@12.0.1/AbstractInterruptibleChannel.java:208)
at java.nio.channels.spi.AbstractInterruptibleChannel.end(java.base@12.0.1/AbstractInterruptibleChannel.java:195)
at sun.nio.ch.DatagramChannelImpl.endRead(java.base@12.0.1/DatagramChannelImpl.java:396)
at sun.nio.ch.DatagramChannelImpl.receive(java.base@12.0.1/DatagramChannelImpl.java:453)
at sun.nio.ch.DatagramChannelImpl.connect(java.base@12.0.1/DatagramChannelImpl.java:869)
- locked <0x00000006294856e8> (a java.lang.Object)
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DeadlockTest
{
private static final Logger LOG = LoggerFactory.getLogger(DeadlockTest.class);
private DatagramChannel receiver;
private InetSocketAddress target = new InetSocketAddress("localhost", 42421);
private boolean running = true;
private class Sender implements Runnable
{
private Thread thisThread = null;
/**
* @see java.lang.Runnable#run()
*/
@Override
public void run()
{
thisThread = Thread.currentThread();
while (running)
{
try
{
DatagramChannel sender = DatagramChannel.open();
sender.setOption(StandardSocketOptions.SO_REUSEADDR, true);
sender.connect(target);
LOG.info("Sending");
sender.send(ByteBuffer.allocate(100).putInt(1), target);
LOG.info("Sent");
Thread.sleep(ThreadLocalRandom.current().nextLong(0, 100));
}
catch (Exception e)
{
//LOG.warn("Caught exception:", e);
}
finally
{
if (Thread.interrupted())
{
LOG.info("Was interrupted");
}
}
}
}
public void interruptThis()
{
if (thisThread != null)
{
thisThread.interrupt();
}
}
}
@Test
public void testDeadlock() throws IOException, InterruptedException
{
receiver = DatagramChannel.open();
receiver.setOption(StandardSocketOptions.SO_REUSEADDR, true);
receiver.bind(new InetSocketAddress(42421));
ExecutorService executor = Executors.newSingleThreadExecutor();
Sender senderActor = new Sender();
executor.submit(senderActor);
while (running)
{
LOG.info("Before interrupt");
senderActor.interruptThis();
LOG.info("After interrupt");
// Sooner or later, you stop seeing this message.
Thread.sleep(ThreadLocalRandom.current().nextLong(0, 100));
}
}
}
---------- END SOURCE ----------
FREQUENCY : occasionally
If you interrupt a thread that is opening a DatagramChannel, it sometimes deadlocks.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
On one thread, open a DatagramChannel, send a packet, and close the channel.
On a second thread, interrupt the first thread.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
First thread is interrupted successfully and aborts its blocking operations in a timely manner, likely throwing an InterruptedException
No deadlocks occur
ACTUAL -
Deadlock occurs sometimes.
Found one Java-level deadlock:
=============================
"main":
waiting to lock monitor 0x00007ff5d0006980 (object 0x00000006294856e8, a java.lang.Object),
which is held by "pool-1-thread-1"
"pool-1-thread-1":
waiting to lock monitor 0x00007ff5d0008b80 (object 0x00000006281ddf18, a java.lang.Object),
which is held by "main"
Java stack information for the threads listed above:
===================================================
"main":
at sun.nio.ch.DatagramChannelImpl.implCloseSelectableChannel(java.base@12.0.1/DatagramChannelImpl.java:1149)
- waiting to lock <0x00000006294856e8> (a java.lang.Object)
at java.nio.channels.spi.AbstractSelectableChannel.implCloseChannel(java.base@12.0.1/AbstractSelectableChannel.java:242)
at java.nio.channels.spi.AbstractInterruptibleChannel$1.interrupt(java.base@12.0.1/AbstractInterruptibleChannel.java:162)
- locked <0x0000000629485658> (a java.lang.Object)
at java.lang.Thread.interrupt(java.base@12.0.1/Thread.java:994)
- locked <0x00000006281ddf18> (a java.lang.Object)
"pool-1-thread-1":
at java.lang.Thread.blockedOn(java.base@12.0.1/Thread.java:238)
- waiting to lock <0x00000006281ddf18> (a java.lang.Object)
at java.lang.System$2.blockedOn(java.base@12.0.1/System.java:2173)
at java.nio.channels.spi.AbstractInterruptibleChannel.blockedOn(java.base@12.0.1/AbstractInterruptibleChannel.java:208)
at java.nio.channels.spi.AbstractInterruptibleChannel.end(java.base@12.0.1/AbstractInterruptibleChannel.java:195)
at sun.nio.ch.DatagramChannelImpl.endRead(java.base@12.0.1/DatagramChannelImpl.java:396)
at sun.nio.ch.DatagramChannelImpl.receive(java.base@12.0.1/DatagramChannelImpl.java:453)
at sun.nio.ch.DatagramChannelImpl.connect(java.base@12.0.1/DatagramChannelImpl.java:869)
- locked <0x00000006294856e8> (a java.lang.Object)
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DeadlockTest
{
private static final Logger LOG = LoggerFactory.getLogger(DeadlockTest.class);
private DatagramChannel receiver;
private InetSocketAddress target = new InetSocketAddress("localhost", 42421);
private boolean running = true;
private class Sender implements Runnable
{
private Thread thisThread = null;
/**
* @see java.lang.Runnable#run()
*/
@Override
public void run()
{
thisThread = Thread.currentThread();
while (running)
{
try
{
DatagramChannel sender = DatagramChannel.open();
sender.setOption(StandardSocketOptions.SO_REUSEADDR, true);
sender.connect(target);
LOG.info("Sending");
sender.send(ByteBuffer.allocate(100).putInt(1), target);
LOG.info("Sent");
Thread.sleep(ThreadLocalRandom.current().nextLong(0, 100));
}
catch (Exception e)
{
//LOG.warn("Caught exception:", e);
}
finally
{
if (Thread.interrupted())
{
LOG.info("Was interrupted");
}
}
}
}
public void interruptThis()
{
if (thisThread != null)
{
thisThread.interrupt();
}
}
}
@Test
public void testDeadlock() throws IOException, InterruptedException
{
receiver = DatagramChannel.open();
receiver.setOption(StandardSocketOptions.SO_REUSEADDR, true);
receiver.bind(new InetSocketAddress(42421));
ExecutorService executor = Executors.newSingleThreadExecutor();
Sender senderActor = new Sender();
executor.submit(senderActor);
while (running)
{
LOG.info("Before interrupt");
senderActor.interruptThis();
LOG.info("After interrupt");
// Sooner or later, you stop seeing this message.
Thread.sleep(ThreadLocalRandom.current().nextLong(0, 100));
}
}
}
---------- END SOURCE ----------
FREQUENCY : occasionally