From issues-return-67526-archive-asf-public=cust-asf.ponee.io@commons.apache.org Mon Apr 30 10:33:05 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 168A3180675 for ; Mon, 30 Apr 2018 10:33:04 +0200 (CEST) Received: (qmail 82866 invoked by uid 500); 30 Apr 2018 08:33:04 -0000 Mailing-List: contact issues-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: issues@commons.apache.org Delivered-To: mailing list issues@commons.apache.org Received: (qmail 82799 invoked by uid 99); 30 Apr 2018 08:33:03 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 30 Apr 2018 08:33:03 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 7A3ACC2CDA for ; Mon, 30 Apr 2018 08:33:03 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -110.301 X-Spam-Level: X-Spam-Status: No, score=-110.301 tagged_above=-999 required=6.31 tests=[ENV_AND_HDR_SPF_MATCH=-0.5, RCVD_IN_DNSWL_MED=-2.3, SPF_PASS=-0.001, USER_IN_DEF_SPF_WL=-7.5, USER_IN_WHITELIST=-100] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id knotbqNSn84s for ; Mon, 30 Apr 2018 08:33:02 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTP id ADB505FB66 for ; Mon, 30 Apr 2018 08:33:01 +0000 (UTC) Received: from jira-lw-us.apache.org (unknown [207.244.88.139]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id A5531E0175 for ; Mon, 30 Apr 2018 08:33:00 +0000 (UTC) Received: from jira-lw-us.apache.org (localhost [127.0.0.1]) by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id 2382F21208 for ; Mon, 30 Apr 2018 08:33:00 +0000 (UTC) Date: Mon, 30 Apr 2018 08:33:00 +0000 (UTC) From: "Pavel Kolesov (JIRA)" To: issues@commons.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Commented] (POOL-340) borrowObject is stuck, if create fails MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/POOL-340?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16458398#comment-16458398 ] Pavel Kolesov commented on POOL-340: ------------------------------------ [~garydgregory], thank you for your response and sorry for the delay. I've come up with such test (not the shortest one, unfortunately): {code} package org.apache.commons.pool2.impl; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.pool2.BasePooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; public class GenericObjectPoolTest { @Test(timeout = 10_000) @Ignore("Doesn't pass, waiting for https://issues.apache.org/jira/browse/POOL-340") public void testBorrowObjectStuck() { SingleObjectFactory factory = new SingleObjectFactory(); GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxIdle(1); config.setMaxTotal(1); config.setBlockWhenExhausted(true); config.setMinIdle(0); config.setTestOnBorrow(true); config.setTestOnReturn(true); config.setTestWhileIdle(false); config.setTimeBetweenEvictionRunsMillis(-1); config.setMinEvictableIdleTimeMillis(-1); config.setSoftMinEvictableIdleTimeMillis(-1); config.setMaxWaitMillis(-1); GenericObjectPool pool = new GenericObjectPool<>(factory, config); AtomicBoolean failed = new AtomicBoolean(); CountDownLatch barrier = new CountDownLatch(1); Thread thread1 = new Thread(new WinnerRunnable(pool, barrier, failed)); thread1.start(); // wait for object to be created while(!factory.created.get()) { sleepIgnoreException(5); } // now borrow barrier.countDown(); try { pool.borrowObject(); } catch (Exception e) { e.printStackTrace(); } Assert.assertFalse(failed.get()); } private static class SingleObjectFactory extends BasePooledObjectFactory { private final AtomicBoolean created = new AtomicBoolean(); private final AtomicBoolean validated = new AtomicBoolean(); @Override public Object create() throws Exception { if (!created.getAndSet(true)) { return new Object(); } throw new Exception("Already created"); } @Override public PooledObject wrap(Object obj) { return new DefaultPooledObject<>(new Object()); } @Override public boolean validateObject(PooledObject p) { // return valid once if (!validated.getAndSet(true)) { return true; } System.out.println("invalid"); return false; } } private static class WinnerRunnable implements Runnable { private final GenericObjectPool pool; private final AtomicBoolean failed; private final CountDownLatch barrier; private WinnerRunnable(GenericObjectPool pool, CountDownLatch barrier, AtomicBoolean failed) { this.pool = pool; this.failed = failed; this.barrier = barrier; } @Override public void run() { try { Object obj = pool.borrowObject(); // wait for another thread to start borrowObject if (!barrier.await(5, TimeUnit.SECONDS)) { System.out.println("Timeout waiting"); failed.set(true); } else { // just to make sure, borrowObject has started waiting on queue sleepIgnoreException(1000); } pool.returnObject(obj); } catch (Exception e) { failed.set(true); e.printStackTrace(); } } } private static void sleepIgnoreException(long millis) { try { Thread.sleep(millis); } catch(Throwable e) { // ignore } } } {code} > borrowObject is stuck, if create fails > -------------------------------------- > > Key: POOL-340 > URL: https://issues.apache.org/jira/browse/POOL-340 > Project: Commons Pool > Issue Type: Bug > Affects Versions: 2.4, 2.4.1, 2.4.2, 2.4.3, 2.5.0 > Reporter: Pavel Kolesov > Priority: Critical > > After changes in 2.4.3 there is a high chance of a scenario, in which borrowObject waits infinitely, if create fails or no one calls a create. > {noformat} > java.lang.Thread.State: WAITING (parking) > at sun.misc.Unsafe.park(Native Method) > - parking to wait for <0x0000000083cfd978> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) > at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) > at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) > at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:583) > at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:442) > at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) > {noformat} > If pool is exhausted, when borrowObject tries to get idle object, it waits for new object to be created. > If all objects are returned to pool invalid and destroyed, and it is impossible to create a new one, borrowObject will not return. > Even if afterwards it is becomes possible to crate a new object but no one creates it, borrowObject will not return either. -- This message was sent by Atlassian JIRA (v7.6.3#76005)