Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8228765

Deadlock between DatagramChannel.connect() and Thread.interrupt()

    XMLWordPrintable

Details

    • 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


      Attachments

        Activity

          People

            psonal Pallavi Sonal (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: