Re: ClosedChannelException on Thread Interrupt

692 views
Skip to first unread message

Thomas Mueller

unread,
May 14, 2013, 3:36:00 PM5/14/13
to H2 Google Group
Hi,

It is a known behavior of Windows that if you interrupt a thread that is currently writing using a FileChannel, that the file is closed. This has been found in other projects as well, for example Apache Lucene and Apache Jackrabbit:




One solution is to *not* interrupt the thread. Another is to *not* use NIO, at least under Windows.

Regards,
Thomas


On Tue, May 14, 2013 at 6:53 PM, abhinav mehrotra <abhinav....@gmail.com> wrote:

I am getting following exception on killing the thread. The exception comes when "nio" (dbc:h2:nio:test) is used while creating the connection. However, without "nio" there is no exception.

Also, once this exception occurs DB is corrupted and is not able to recover on restart.

org.h2.jdbc.JdbcSQLException: IO Exception: "java.nio.channels.ClosedChannelException"; "nio:test.h2.db" [90031-147]

    at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
    at org.h2.message.DbException.get(DbException.java:156)
    at org.h2.message.DbException.convertIOException(DbException.java:313)
    at org.h2.store.FileStore.write(FileStore.java:342)
    at org.h2.store.PageStore.writePage(PageStore.java:1309)
    at org.h2.store.PageStreamData.write(PageStreamData.java:105)
    at org.h2.store.PageOutputStream.storePage(PageOutputStream.java:148)
    at org.h2.store.PageOutputStream.write(PageOutputStream.java:130)
    at org.h2.store.PageLog.write(PageLog.java:529)
    at org.h2.store.PageLog.commit(PageLog.java:549)
    at org.h2.store.PageStore.commit(PageStore.java:1417)
    at org.h2.engine.Database.commit(Database.java:1685)
    at org.h2.engine.Session.commit(Session.java:459)
    at org.h2.command.Command.stop(Command.java:170)
    at org.h2.command.Command.executeUpdate(Command.java:250)
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:143)
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
    at testH2.insert(testH2.java:33)
    at testH2$1.run(testH2.java:43)
    at java.lang.Thread.run(Thread.java:722)

Following is the sample program:


public class testH2 {
    static Connection conn = null;
    static  PreparedStatement statP = null;
    static{
           try {
            Class.forName("org.h2.Driver");
            conn = DriverManager.getConnection("jdbc:h2:nio:test");

            statP = conn.prepareStatement("insert into test1 values(1, 'Hello')");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
          
    }

    public void insert() throws SQLException{
        statP.executeUpdate();
    }
   
    public static void main(String... args) throws Exception {
       
       Thread t =  new Thread(new Runnable(){
            public void run(){
                testH2 t = new testH2();
                for (int i=0;i<50000;i++){
                    try {
                        t.insert();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        );
       t.start();
       Thread.sleep(1);
       t.interrupt();
       testH2 tx = new testH2();
       tx.insert();
      
    
    }
}

Any references or pointers would be highly appreciated. 

Thanks in advance


--
You received this message because you are subscribed to the Google Groups "H2 Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to h2-database...@googlegroups.com.
To post to this group, send email to h2-da...@googlegroups.com.
Visit this group at http://groups.google.com/group/h2-database?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

great_aw...@msn.com

unread,
May 2, 2017, 3:22:40 PM5/2/17
to H2 Database
We are currently getting tons of these NIO closed channel exceptions. So many, that the trace.db file wrapped.

Versions
HikariCP 2.4.4
DataNucleus 4.1.6
H2 - 1.4.194

Done a bunch of searching and have come up empty. Recently upgrade to latest H2 and Hikari to try and fix.

Anybody have any ideas?

org.h2.jdbc.JdbcSQLException: General error: "java.lang.IllegalStateException: Reading from nio:/home/network/Database.mv.db failed; file length -1 read length 1024 at 4378954 [1.4.194/1]"; SQL statement:
UPDATE STATUS SET ISALIVE=? WHERE STATUS_ID=? [50000-194]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:168)
at org.h2.message.DbException.convert(DbException.java:295)
at org.h2.command.Command.executeUpdate(Command.java:266)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:160)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:146)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at org.datanucleus.store.rdbms.ParamLoggingPreparedStatement.executeUpdate(ParamLoggingPreparedStatement.java:393)
at org.datanucleus.store.rdbms.SQLController.executeStatementUpdate(SQLController.java:431)
at org.datanucleus.store.rdbms.request.UpdateRequest.execute(UpdateRequest.java:376)
at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.updateObjectInTable(RDBMSPersistenceHandler.java:409)
at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.updateObject(RDBMSPersistenceHandler.java:383)
at org.datanucleus.state.StateManagerImpl.flush(StateManagerImpl.java:4585)
at org.datanucleus.flush.FlushOrdered.execute(FlushOrdered.java:106)
at org.datanucleus.ExecutionContextImpl.flushInternal(ExecutionContextImpl.java:4054)
at org.datanucleus.ExecutionContextImpl.processNontransactionalAtomicChanges(ExecutionContextImpl.java:1430)
at org.datanucleus.ExecutionContextImpl.persistObject(ExecutionContextImpl.java:1813)
at org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:715)
at org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:740)
at com.nimsoft.probes.network.snmpcollector.model.probe.SnmpDeviceStatusCache.updateStatus(SnmpDeviceStatusCache.java:90)
at com.nimsoft.snmppoller.poller.collector.snmp.PolledCollector.checkReachableAndReset(PolledCollector.java:492)
at com.nimsoft.snmppoller.poller.collector.snmp.PolledCollector.initialize(PolledCollector.java:71)
at com.nimsoft.snmppoller.poller.collector.snmp.PolledCollector.run(PolledCollector.java:241)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Reading from nio:/home/network/Database.mv.db failed; file length -1 read length 1024 at 4378954 [1.4.194/1]
at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:765)
at org.h2.mvstore.DataUtils.readFully(DataUtils.java:435)
at org.h2.mvstore.FileStore.readFully(FileStore.java:98)
at org.h2.mvstore.Page.read(Page.java:190)
at org.h2.mvstore.MVStore.readPage(MVStore.java:1952)
at org.h2.mvstore.MVMap.readPage(MVMap.java:741)
at org.h2.mvstore.Page.getChildPage(Page.java:217)
at org.h2.mvstore.Cursor.min(Cursor.java:129)
at org.h2.mvstore.Cursor.hasNext(Cursor.java:36)
at org.h2.mvstore.db.TransactionStore$TransactionMap$2.fetchNext(TransactionStore.java:1459)
at org.h2.mvstore.db.TransactionStore$TransactionMap$2.<init>(TransactionStore.java:1455)
at org.h2.mvstore.db.TransactionStore$TransactionMap.entryIterator(TransactionStore.java:1449)
at org.h2.mvstore.db.MVPrimaryIndex.find(MVPrimaryIndex.java:359)
at org.h2.mvstore.db.MVDelegateIndex.find(MVDelegateIndex.java:75)
at org.h2.index.BaseIndex.find(BaseIndex.java:128)
at org.h2.index.IndexCursor.find(IndexCursor.java:169)
at org.h2.table.TableFilter.next(TableFilter.java:468)
at org.h2.command.dml.Update.update(Update.java:102)
at org.h2.command.CommandContainer.update(CommandContainer.java:101)
at org.h2.command.Command.executeUpdate(Command.java:258)
... 23 more
Caused by: java.nio.channels.ClosedChannelException
at sun.nio.ch.FileChannelImpl.ensureOpen(FileChannelImpl.java:110)
at sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:721)
at org.h2.store.fs.FileNio.read(FilePathNio.java:74)
at org.h2.mvstore.DataUtils.readFully(DataUtils.java:421)
... 41 more

Noel Grandin

unread,
May 2, 2017, 3:59:56 PM5/2/17
to h2-da...@googlegroups.com

great_aw...@msn.com

unread,
May 2, 2017, 4:56:26 PM5/2/17
to H2 Database
Thanks, Noel.
I have seen that post.
In regards to the retry option mentioned, is that just added to the URL like this?
"jdbc:h2:retry:./dbfilename;"

hendrik

unread,
May 9, 2017, 5:37:49 AM5/9/17
to H2 Database


On Tuesday, May 2, 2017 at 10:56:26 PM UTC+2, great_aw...@msn.com wrote:
In regards to the retry option mentioned, is that just added to the URL like this?
"jdbc:h2:retry:./dbfilename;"

Yes. That seems to be the format.

I just ran into this issue... first thought that H2 1.4 is simply broken and not ready to be used yet and then—with luck—found this issue.

I use H2 as embedded database in an application with UI. And to dynamically react to user input, I use Thread.interrupt() all the time (basically canceling database reads that are not needed anymore).

I expect H2 to respond gracefully to such interruptions. That is, throw a SQLException (I think that happened in 1.3) or something comparable. IMHO the current default behavior is not desirable and should be changed.

Or is there a common scenario in which I would want to close the whole database for all threads when a single thread is interrupted—a perfectly normal thing to happen in all kinds of applications, but especially apps with UI?

It seems that changing the current default behavior could certainly reduce the WTF-factor.
Reply all
Reply to author
Forward
0 new messages