[ https://issues.apache.org/jira/browse/IO-647?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Daniel Dudzika updated IO-647: ------------------------------ Description: Hello, today I found out a potential issue around GenericObjectPool and removing "abandoned" objects functionality. During the accident one of our customers faced with database outage. After this our product become unreachable. This state was caused by two threads. 1st "survived" the outage and still possessing the connection it operates on the database, 2nd one was forced to remove "abandoned" objects. This situation cause that 2nd thread was waiting for 1st one until this 1st thread end his database operation. More context can be found in the stack traces attached below. {code:java} "1st thread" #434 daemon prio=5 os_prio=0 tid=0x00007f9e7746f000 nid=0x9680 runnable [0x00007f9d29c70000]"1st thread" #434 daemon prio=5 os_prio=0 tid=0x00007f9e7746f000 nid=0x9680 runnable [0x00007f9d29c70000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.FileDispatcherImpl.read0(Native Method) at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) at sun.nio.ch.IOUtil.read(IOUtil.java:197) at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380) - locked <0x00007fa23958bc48> (a java.lang.Object) at oracle.net.nt.TimeoutSocketChannel.read(TimeoutSocketChannel.java:144) at oracle.net.ns.NIOHeader.readHeaderBuffer(NIOHeader.java:82) at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:139) at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:101) at oracle.net.ns.NIONSDataChannel.readDataFromSocketChannel(NIONSDataChannel.java:80) at oracle.jdbc.driver.T4CMAREngineNIO.prepareForReading(T4CMAREngineNIO.java:102) at oracle.jdbc.driver.T4CMAREngineNIO.getNBytes(T4CMAREngineNIO.java:679) at oracle.jdbc.driver.T4CMAREngineNIO.unmarshalNBytes(T4CMAREngineNIO.java:651) at oracle.jdbc.driver.DynamicByteArray.unmarshalBuffer(DynamicByteArray.java:334) at oracle.jdbc.driver.DynamicByteArray.unmarshalCLR(DynamicByteArray.java:226) at oracle.jdbc.driver.T4CNumberAccessor.unmarshalBytes(T4CNumberAccessor.java:191) at oracle.jdbc.driver.T4CNumberAccessor.unmarshalOneRow(T4CNumberAccessor.java:173) at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:1526) at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:1289) at oracle.jdbc.driver.T4C8Oall.readRXD(T4C8Oall.java:850) at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:543) at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252) at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:612) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:226) at oracle.jdbc.driver.T4CPreparedStatement.fetch(T4CPreparedStatement.java:1023) at oracle.jdbc.driver.OracleStatement.fetchMoreRows(OracleStatement.java:3353) at oracle.jdbc.driver.InsensitiveScrollableResultSet.fetchMoreRows(InsensitiveScrollableResultSet.java:736) at oracle.jdbc.driver.InsensitiveScrollableResultSet.absoluteInternal(InsensitiveScrollableResultSet.java:692) at oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:406) - locked <0x00007fa23958e580> (a oracle.jdbc.driver.T4CConnection) at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191) at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191) {code} {code:java} "2nd thread" #376448 daemon prio=5 os_prio=0 tid=0x00007f9e581db000 nid=0x1239 waiting for monitor entry [0x00007f9a75ff2000]"2nd thread" #376448 daemon prio=5 os_prio=0 tid=0x00007f9e581db000 nid=0x1239 waiting for monitor entry [0x00007f9a75ff2000] java.lang.Thread.State: BLOCKED (on object monitor) at oracle.jdbc.driver.InsensitiveScrollableResultSet.close(InsensitiveScrollableResultSet.java:190) - waiting to lock <0x00007fa23958e580> (a oracle.jdbc.driver.T4CConnection) at org.apache.commons.dbcp2.DelegatingResultSet.close(DelegatingResultSet.java:170) at org.apache.commons.dbcp2.DelegatingStatement.close(DelegatingStatement.java:150) at org.apache.commons.dbcp2.DelegatingConnection.passivate(DelegatingConnection.java:631) at org.apache.commons.dbcp2.PoolableConnection.passivate(PoolableConnection.java:127) at org.apache.commons.dbcp2.DelegatingConnection.closeInternal(DelegatingConnection.java:232) at org.apache.commons.dbcp2.PoolableConnection.reallyClose(PoolableConnection.java:243) at org.apache.commons.dbcp2.PoolableConnectionFactory.destroyObject(PoolableConnectionFactory.java:334) at org.apache.commons.pool2.impl.GenericObjectPool.destroy(GenericObjectPool.java:890) at org.apache.commons.pool2.impl.GenericObjectPool.invalidateObject(GenericObjectPool.java:649) - locked <0x00007fa2651f85f8> (a org.apache.commons.pool2.impl.DefaultPooledObject) at org.apache.commons.pool2.impl.GenericObjectPool.removeAbandoned(GenericObjectPool.java:1022) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:418) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134) at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1533) {code} Cheers, Daniel Dudziak Atlassian Developer was: Hello, today I found out a potential issue around GenericObjectPool and removing "abandoned" objects functionality. During the accident one of our customers faced with database outage. After this our product become unreachable. This state was caused by two threads. 1st "survived" the outage and still possessing the connection it operates on the database, 2nd one was forced to remove "abandoned" objects. This situation cause that 2nd thread was waiting for 1st one until this 1st thread end his database operation. More context can be found in the stack traces attached below. {code:java} "1st thread" #434 daemon prio=5 os_prio=0 tid=0x00007f9e7746f000 nid=0x9680 runnable [0x00007f9d29c70000]"1st thread" #434 daemon prio=5 os_prio=0 tid=0x00007f9e7746f000 nid=0x9680 runnable [0x00007f9d29c70000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.FileDispatcherImpl.read0(Native Method) at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) at sun.nio.ch.IOUtil.read(IOUtil.java:197) at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380) - locked <0x00007fa23958bc48> (a java.lang.Object) at oracle.net.nt.TimeoutSocketChannel.read(TimeoutSocketChannel.java:144) at oracle.net.ns.NIOHeader.readHeaderBuffer(NIOHeader.java:82) at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:139) at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:101) at oracle.net.ns.NIONSDataChannel.readDataFromSocketChannel(NIONSDataChannel.java:80) at oracle.jdbc.driver.T4CMAREngineNIO.prepareForReading(T4CMAREngineNIO.java:102) at oracle.jdbc.driver.T4CMAREngineNIO.getNBytes(T4CMAREngineNIO.java:679) at oracle.jdbc.driver.T4CMAREngineNIO.unmarshalNBytes(T4CMAREngineNIO.java:651) at oracle.jdbc.driver.DynamicByteArray.unmarshalBuffer(DynamicByteArray.java:334) at oracle.jdbc.driver.DynamicByteArray.unmarshalCLR(DynamicByteArray.java:226) at oracle.jdbc.driver.T4CNumberAccessor.unmarshalBytes(T4CNumberAccessor.java:191) at oracle.jdbc.driver.T4CNumberAccessor.unmarshalOneRow(T4CNumberAccessor.java:173) at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:1526) at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:1289) at oracle.jdbc.driver.T4C8Oall.readRXD(T4C8Oall.java:850) at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:543) at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252) at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:612) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:226) at oracle.jdbc.driver.T4CPreparedStatement.fetch(T4CPreparedStatement.java:1023) at oracle.jdbc.driver.OracleStatement.fetchMoreRows(OracleStatement.java:3353) at oracle.jdbc.driver.InsensitiveScrollableResultSet.fetchMoreRows(InsensitiveScrollableResultSet.java:736) at oracle.jdbc.driver.InsensitiveScrollableResultSet.absoluteInternal(InsensitiveScrollableResultSet.java:692) at oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:406) - locked <0x00007fa23958e580> (a oracle.jdbc.driver.T4CConnection) at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191) at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191) {code} {code:java} "2nd thread" #376448 daemon prio=5 os_prio=0 tid=0x00007f9e581db000 nid=0x1239 waiting for monitor entry [0x00007f9a75ff2000]"2nd thread" #376448 daemon prio=5 os_prio=0 tid=0x00007f9e581db000 nid=0x1239 waiting for monitor entry [0x00007f9a75ff2000] java.lang.Thread.State: BLOCKED (on object monitor) at oracle.jdbc.driver.InsensitiveScrollableResultSet.close(InsensitiveScrollableResultSet.java:190) - waiting to lock <0x00007fa23958e580> (a oracle.jdbc.driver.T4CConnection) at org.apache.commons.dbcp2.DelegatingResultSet.close(DelegatingResultSet.java:170) at org.apache.commons.dbcp2.DelegatingStatement.close(DelegatingStatement.java:150) at org.apache.commons.dbcp2.DelegatingConnection.passivate(DelegatingConnection.java:631) at org.apache.commons.dbcp2.PoolableConnection.passivate(PoolableConnection.java:127) at org.apache.commons.dbcp2.DelegatingConnection.closeInternal(DelegatingConnection.java:232) at org.apache.commons.dbcp2.PoolableConnection.reallyClose(PoolableConnection.java:243) at org.apache.commons.dbcp2.PoolableConnectionFactory.destroyObject(PoolableConnectionFactory.java:334) at org.apache.commons.pool2.impl.GenericObjectPool.destroy(GenericObjectPool.java:890) at org.apache.commons.pool2.impl.GenericObjectPool.invalidateObject(GenericObjectPool.java:649) - locked <0x00007fa2651f85f8> (a org.apache.commons.pool2.impl.DefaultPooledObject) at org.apache.commons.pool2.impl.GenericObjectPool.removeAbandoned(GenericObjectPool.java:1022) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:418) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134) at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1533) {code} Cheers, Daniel Dudziak Atlassian Developer > Race condition in the GenericObjectPool in removeAbandoned functionality > ------------------------------------------------------------------------ > > Key: IO-647 > URL: https://issues.apache.org/jira/browse/IO-647 > Project: Commons IO > Issue Type: Bug > Affects Versions: 2.1 > Reporter: Daniel Dudzika > Priority: Minor > > Hello, > today I found out a potential issue around GenericObjectPool and removing > "abandoned" objects functionality. > During the accident one of our customers faced with database outage. > After this our product become unreachable. This state was caused by two > threads. > 1st "survived" the outage and still possessing the connection it operates on > the database, > 2nd one was forced to remove "abandoned" objects. > This situation cause that 2nd thread was waiting for 1st one until this 1st > thread end his database operation. > More context can be found in the stack traces attached below. > {code:java} > "1st thread" #434 daemon prio=5 os_prio=0 tid=0x00007f9e7746f000 nid=0x9680 > runnable [0x00007f9d29c70000]"1st thread" #434 daemon prio=5 os_prio=0 > tid=0x00007f9e7746f000 nid=0x9680 runnable [0x00007f9d29c70000] > java.lang.Thread.State: RUNNABLE at > sun.nio.ch.FileDispatcherImpl.read0(Native Method) at > sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) at > sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) at > sun.nio.ch.IOUtil.read(IOUtil.java:197) at > sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380) - locked > <0x00007fa23958bc48> (a java.lang.Object) at > oracle.net.nt.TimeoutSocketChannel.read(TimeoutSocketChannel.java:144) at > oracle.net.ns.NIOHeader.readHeaderBuffer(NIOHeader.java:82) at > oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:139) at > oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:101) at > oracle.net.ns.NIONSDataChannel.readDataFromSocketChannel(NIONSDataChannel.java:80) > at > oracle.jdbc.driver.T4CMAREngineNIO.prepareForReading(T4CMAREngineNIO.java:102) > at oracle.jdbc.driver.T4CMAREngineNIO.getNBytes(T4CMAREngineNIO.java:679) at > oracle.jdbc.driver.T4CMAREngineNIO.unmarshalNBytes(T4CMAREngineNIO.java:651) > at > oracle.jdbc.driver.DynamicByteArray.unmarshalBuffer(DynamicByteArray.java:334) > at > oracle.jdbc.driver.DynamicByteArray.unmarshalCLR(DynamicByteArray.java:226) > at > oracle.jdbc.driver.T4CNumberAccessor.unmarshalBytes(T4CNumberAccessor.java:191) > at > oracle.jdbc.driver.T4CNumberAccessor.unmarshalOneRow(T4CNumberAccessor.java:173) > at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:1526) at > oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:1289) at > oracle.jdbc.driver.T4C8Oall.readRXD(T4C8Oall.java:850) at > oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:543) at > oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252) at > oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:612) at > oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:226) > at > oracle.jdbc.driver.T4CPreparedStatement.fetch(T4CPreparedStatement.java:1023) > at > oracle.jdbc.driver.OracleStatement.fetchMoreRows(OracleStatement.java:3353) > at > oracle.jdbc.driver.InsensitiveScrollableResultSet.fetchMoreRows(InsensitiveScrollableResultSet.java:736) > at > oracle.jdbc.driver.InsensitiveScrollableResultSet.absoluteInternal(InsensitiveScrollableResultSet.java:692) > at > oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:406) > - locked <0x00007fa23958e580> (a oracle.jdbc.driver.T4CConnection) at > org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191) > at > org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191) > {code} > {code:java} > "2nd thread" #376448 daemon prio=5 os_prio=0 tid=0x00007f9e581db000 > nid=0x1239 waiting for monitor entry [0x00007f9a75ff2000]"2nd thread" #376448 > daemon prio=5 os_prio=0 tid=0x00007f9e581db000 nid=0x1239 waiting for monitor > entry [0x00007f9a75ff2000] java.lang.Thread.State: BLOCKED (on object > monitor) at > oracle.jdbc.driver.InsensitiveScrollableResultSet.close(InsensitiveScrollableResultSet.java:190) > - waiting to lock <0x00007fa23958e580> (a oracle.jdbc.driver.T4CConnection) > at > org.apache.commons.dbcp2.DelegatingResultSet.close(DelegatingResultSet.java:170) > at > org.apache.commons.dbcp2.DelegatingStatement.close(DelegatingStatement.java:150) > at > org.apache.commons.dbcp2.DelegatingConnection.passivate(DelegatingConnection.java:631) > at > org.apache.commons.dbcp2.PoolableConnection.passivate(PoolableConnection.java:127) > at > org.apache.commons.dbcp2.DelegatingConnection.closeInternal(DelegatingConnection.java:232) > at > org.apache.commons.dbcp2.PoolableConnection.reallyClose(PoolableConnection.java:243) > at > org.apache.commons.dbcp2.PoolableConnectionFactory.destroyObject(PoolableConnectionFactory.java:334) > at > org.apache.commons.pool2.impl.GenericObjectPool.destroy(GenericObjectPool.java:890) > at > org.apache.commons.pool2.impl.GenericObjectPool.invalidateObject(GenericObjectPool.java:649) > - locked <0x00007fa2651f85f8> (a > org.apache.commons.pool2.impl.DefaultPooledObject) at > org.apache.commons.pool2.impl.GenericObjectPool.removeAbandoned(GenericObjectPool.java:1022) > at > org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:418) > at > org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) > at > org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134) > at > org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1533) > {code} > Cheers, > Daniel Dudziak > Atlassian Developer -- This message was sent by Atlassian Jira (v8.3.4#803005)