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

ReentrantLock calls can hang from lack of stack space

    XMLWordPrintable

    Details

      Description

      FULL PRODUCT VERSION :
      java version " 1.7.0_06 "
      Java(TM) SE Runtime Environment (build 1.7.0_06-b24)
      Java HotSpot(TM) 64-Bit Server VM (build 23.2-b09, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      ReentrantLock.unlock() call consumes more stack compared to ReentrantLock.lock().
      This can cause paired lock/unlocks calls to fail in locked state given a tight
      stack situation. The failing thread exits with an out of stack error, but
      the rest of the application will likely hang due to the stuck lock.

        Suggested fix:

      1. Increase ReentrantLock.lock() stack usage to be equal or greater than ReentrantLock.unlock().
      2. Enhance ReentrantLock.lock() to detect an owner's thread death and clean up held locks.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the supplied test case and it will hang. Failure is stack size dependent.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Paired lock / unlock calls should work.
      ACTUAL -
      Lock call goes through but unlock call fails.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      stack trace in log file and application hung



      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.concurrent.locks.ReentrantLock;

      public class TestReentrantLock extends Thread
      {

          static final ReentrantLock myLock = new ReentrantLock();
          
          public static void func1()
          {
              byte a1;
              
              // Bracketed lock and unlock.
              myLock.lock();
              try
              {
              }
              finally
              {
                  myLock.unlock();
              }
              
              myLock.lock();
              try
              {
                  // Simulate stack exhaustion.
                  func1();
              }
              finally
              {
                  myLock.unlock();
              }
          }
          
          public void run()
          {
              // try
              {
                  func1();
              }
              /*
              catch (Throwable ex)
              {
                  // Is the lock currently unlocked, given that
                  // all locks and unlocks are bracketed?
                  if (myLock.isLocked())
                  {
                      System.out.println( " Failed. " );
                  }
                  else
                  {
                      System.out.println( " Passed. " );
                  }
              }
              */
          }
          
          public static void main(String[] args) throws Exception
          {
              Thread th = new TestReentrantLock();
              th.start();
              th.join();
              System.out.println( " Am I going to be hung? " );
              myLock.lock();
              try
              {
                  System.out.println( " got lock " );
              }
              finally
              {
                  myLock.unlock();
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      no reliable workarounds known

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              coffeys Sean Coffey
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Dates

                Created:
                Updated: