Uploaded image for project: 'Commons Pool'
  1. Commons Pool
  2. POOL-184

Premature starvation in GenericObjectPool when borrowObject() and evict() are executed concurrently

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.5.5
    • 1.5.6
    • None
    • java 1.6.0_24
      Ubuntu 10.10

    Description

      Hi,

      I am encountering a deadlock in GenericObjectPool. It appears in version 1.5.5
      and also in revision 1079385 (March 8th 2011).

      The deadlock manifests when calling borrowObject() and evict() in parallel. I
      have inlined a test that exposes this problem. For this test, the expected
      output is:

      Expected output:
      0
      1
      2
      3
      4
      .....
      498
      499
      DONE

      But when the bug manifests (almost always for this test), the output is:

      Bug output:
      0
      1
      2
      3
      4

      When the bug manifests, the test does not finish, it just gets stuck after
      printing several values (in this run: 0 1 2 3 4, but in other runs may be
      0 1 2 .. 18 or 0 1 2 or some other value).

      When the loop limit is small (e.g., 11 instead of 5000), the test does finish.

      Also, when running sequentially:

      Pool.borrowObject();
      Pool.evict();

      or vice-versa

      Pool.evict();
      Pool.borrowObject();

      the test still finishes.

      Is this a bug? Is there a patch for it?

      Thanks!

      Adrian

      ================================================================================
      This test is for version 1.5.5. For revision 1079385 one should replace
      setMaxActive() with setMaxTotal()
      ================================================================================
      package org.apache.commons.pool.impl;

      import org.apache.commons.pool.PoolableObjectFactory;

      public class Test01
      {
      public static void main(String[] args) throws Exception

      { Test01 test = new Test01(); test.test(); }

      SimpleFactory Factory = null;
      GenericObjectPool Pool = null;
      Object Obj = null;
      public void test() throws Exception
      {
      Factory = new SimpleFactory();
      Pool = new GenericObjectPool(Factory);
      Pool.setMaxActive(1);
      Pool.addObject();

      for(int i=0; i<5000; i++)
      {
      Thread one = new MyThread(1);
      Thread two = new MyThread(2);
      one.start();
      two.start();
      one.join();
      two.join();

      Pool.returnObject(Obj);
      if(i%10==0)

      { System.out.println(i/10); }

      }
      System.out.println("DONE");
      }

      private class MyThread extends Thread
      {
      int _tid;
      public MyThread(int tid)

      { _tid = tid; }

      public void run()
      {
      try
      {
      if(_tid == 1)

      { Obj = Pool.borrowObject(); }

      if (_tid == 2)
      {
      try

      { Pool.evict(); }

      catch (Exception e) {}
      }
      }
      catch(Exception e)

      { throw new RuntimeException(e); }

      }
      }

      private class SimpleFactory implements PoolableObjectFactory
      {
      public SimpleFactory() {}
      public Object makeObject()

      { return new String("testing"); }

      public void destroyObject(Object obj) {}
      public boolean validateObject(Object obj)

      {return true;}
      public void activateObject(Object obj) throws Exception {}
      public void passivateObject(Object obj) throws Exception {}
      public boolean isThrowExceptionOnActivate() {return true;}

      }
      }
      ================================================================================

      Attachments

        1. stall.txt
          4 kB
          Phil Steitz
        2. Test01.java
          2 kB
          Adrian Nistor

        Activity

          People

            markt Mark Thomas
            adriannistor Adrian Nistor
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: