[prev in list] [next in list] [prev in thread] [next in thread] 

List:       activemq-dev
Subject:    [jira] Created: (AMQ-1956) NPE during broker shutdown when
From:       "Chris Pettitt (JIRA)" <jira () apache ! org>
Date:       2008-09-26 17:38:52
Message-ID: 1357385619.1222450732670.JavaMail.jira () brutus
[Download RAW message or body]

NPE during broker shutdown when useDatabaseLock="false"
-------------------------------------------------------

                 Key: AMQ-1956
                 URL: https://issues.apache.org/activemq/browse/AMQ-1956
             Project: ActiveMQ
          Issue Type: Bug
          Components: Message Store
    Affects Versions: 5.1.0
            Reporter: Chris Pettitt
         Attachments: BrokerStopFailure.java, NoLockerJDBCPersistenceAdapter.java

Steps:

1. Create a broker with the persistence adapter set to not use database locking \
(useDatabaseLock="false") 2. Start broker
3. Stop broker (but keep the process running, as in a servlet container)

Result:

In the logs, I see the following error every 30 seconds:

2008/09/25 15:23:55.506 INFO [org.apache.activemq.store.jdbc.JDBCPersistenceAdapter] \
No longer able to keep the exclusive lock so giving up being a master 2008/09/25 \
15:23:55.506 WARN [org.apache.activemq.store.jdbc.JDBCPersistenceAdapter] Failed to \
stop broker 2008/09/25 15:24:25.504 ERROR \
[org.apache.activemq.store.jdbc.DefaultDatabaseLocker] Failed to update database \
lock: java.lang.NullPointerException java.lang.NullPointerException
        at org.apache.activemq.store.jdbc.DefaultDatabaseLocker.keepAlive(DefaultDatabaseLocker.java:102)
                
        at org.apache.activemq.store.jdbc.JDBCPersistenceAdapter.databaseLockKeepAlive(JDBCPersistenceAdapter.java:458)
                
        at org.apache.activemq.store.jdbc.JDBCPersistenceAdapter$3.run(JDBCPersistenceAdapter.java:260)
                
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:417)
        at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:280)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:135)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:65)
                
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:142)
                
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:166)
                
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
                
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
  at java.lang.Thread.run(Thread.java:613)


Analysis:

During startup, JDBCPersistenceAdapter only initializes the database locker if \
useDatabaseLock if true. This is done through lazy initialization by calling \
getDatabaseLocker (at ~ line 172):

        if (isUseDatabaseLock()) {
            DatabaseLocker service = getDatabaseLocker();
            if (service == null) {
                LOG.warn("No databaseLocker configured for the JDBC Persistence \
Adapter");  } else {
                service.start();
            }
        }

During shutdown, JDBCPersistenceAdapter calls getDatabaseLocker() to shut it down, \
but it does not check if isUseDatabaseLock() is true in this case:

    public synchronized void stop() throws Exception {
        if (clockTicket != null) {
            clockTicket.cancel(true);
            clockTicket = null;
        }
        if (clockDaemon != null) {
            clockDaemon.shutdown();
            clockDaemon = null;
        }
        DatabaseLocker service = getDatabaseLocker();
        if (service != null) {
            service.stop();
        }
    }

This actually causes database locker to be initialized and it subsequently \
lazy-initializes an executor to run a task which calls keepAlive(...). The executor \
threads are set as daemon threads which prevents this issue from showing up when the \
lifetime of the process is the same as the broker. When the broker is deployed in an \
app server which can outlive the broker then the above error is logged every 30 \
seconds.

I'm attaching one way to solve this problem without having to check everywhere if \
useDatabaseLock="false".

Attached:

BrokerStopFailure.java - sample program that reproduces this bug
NoLockerJDBCPersistenceAdapter.java - sample extension to JDBCPersistenceAdapter that \
fixes this bug

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic