I already sent this patches a few weeks ago, but none of them made it
into CVS yet. Thought that they got lost between the more important
threads so I resend them.


I've included a small descprition of the bugs:


The bug in event-package
------------------------

The bug sometimes occurs on disposing of the TPCThreadManager and results
in:

Unexpected condition while releasing worker: Thread[TPCThreadManager Worker 
#0,5,TPCThreadManager]
java.lang.NullPointerException
        at 
org.apache.excalibur.event.command.EventThreadPool.releaseWorker(EventThreadPool.java:141)
        at 
org.apache.excalibur.thread.impl.WorkerThread.recycleThread(WorkerThread.java:134)
        at 
org.apache.excalibur.thread.impl.WorkerThread.run(WorkerThread.java:123)

It's caused by Threads in the EventThreadPool that were still running after
disposing of the Pool.

This was a nasty bug, I had to fix EventThreadPool, AbstractThreadManager and 
TPCThreadManager
(Spend some hours on it). See ThreadManager_disposing.patch for more info.


The bugs in AbstractServiceManager
----------------------------------

1. AbstractServiceManager wraps all ComponentHandlers in a
LEAwareComponentHandler. But the LEAwareComponentHandler isn't
Disposable so none of the componentHandlers ever gets disposed. I've added
an getDelegate() Method to LEAwareComponentHandler and dispose the
delegates on disposing of the Container.

2. If the container gets disposed before all its ComponentHandlers are
prepared, an IllegalStateException("You cannot get a component from a
disposed holder") is thrown by the PrepareHandlerCommands that are still in
the initialization queue. That is correct, because the
ComponentHandlers were disposed in the dispose method after the
previous fix. To solve this, I have added a disable() method to
PrepareHandlerCommand to prevent execution of the command after
disposing of the ComponSee container_disposing.patch for more info


The bug in FortressServiceManager
---------------------------------

The lookup-method consulted the parent ServiceManager if the Service was not
found while the hasService didn't. I just added a call to
m_parent.hasService





Regards

Christopher


Index: src/java/org/apache/excalibur/event/command/AbstractThreadManager.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon-excalibur/event/src/java/org/apache/excalibur/event/command/AbstractThreadManager.java,v
retrieving revision 1.11
diff -u -r1.11 AbstractThreadManager.java
--- src/java/org/apache/excalibur/event/command/AbstractThreadManager.java      
2 Oct 2002 17:49:20 -0000       1.11
+++ src/java/org/apache/excalibur/event/command/AbstractThreadManager.java      
23 Nov 2002 12:20:50 -0000
@@ -207,13 +207,16 @@
                 if( m_pipelines.isEmpty() )
                 {
                     m_done = true;
-                    m_threadControl.join( 1000 );
                 }
             }
             finally
             {
                 m_mutex.release();
             }
+           if ( m_done )
+           {
+               m_threadControl.join( 1000 );
+           }
         }
         catch( InterruptedException ie )
         {
@@ -234,26 +237,26 @@
 
         try
         {
+           // Aquire mutex to clear pipelines and set the m_done flag
             m_mutex.acquire();
             try
             {
                 m_done = true;
-                m_threadControl.join( 1000 );
-
                 Iterator it = m_controls.iterator();
 
                 while( it.hasNext() )
                 {
                     ( (ThreadControl)it.next() ).join( 1000 );
                 }
-
                 m_pipelines.clear();
 
             }
             finally
             {
+               //  C.K. We must release the mutex to give the manager thread a 
chance to terminate.
                 m_mutex.release();
             }
+           m_threadControl.join( 1000 );
         }
         catch( InterruptedException ie )
         {
@@ -261,16 +264,45 @@
         }
     }
 
+
     /**
      * Get rid of the ThreadManager.
      */
-    public void dispose()
+    public void dispose() 
     {
-        deregisterAll();
+        deregisterAll(); 
+ 
+       if (m_threadControl != null && !m_threadControl.isFinished()) 
+       {
+           if( getLogger().isErrorEnabled() )
+           {
+               getLogger().error( "The ThreadManager management thread is 
still active." );
+           }
+       }
 
         m_threadControl = null;
     }
 
+    /** 
+     * Return the thread controlls of all active threads 
+     * (excluding the ThreadManager management thread)
+     */
+    protected ThreadControl[] getThreadControls() {
+       try 
+       {
+           m_mutex.acquire();
+           return (ThreadControl[]) m_controls.toArray(new ThreadControl[0]);
+       } 
+       catch( InterruptedException ie )
+       {
+           return new ThreadControl[0];
+       }
+       finally 
+       {
+           m_mutex.release();
+       }
+    }
+
     /**
      * The code that is run in the background to manage the ThreadPool and the
      * EventPipelines
@@ -331,7 +363,10 @@
                 while( it.hasNext() )
                 {
                     ThreadControl control = (ThreadControl)it.next();
-                    if( control.isFinished() ) it.remove();
+                    if( control.isFinished() ) 
+                   { 
+                       it.remove();
+                   }
                 }
 
                 m_mutex.release();
Index: src/java/org/apache/excalibur/event/command/TPCThreadManager.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon-excalibur/event/src/java/org/apache/excalibur/event/command/TPCThreadManager.java,v
retrieving revision 1.32
diff -u -r1.32 TPCThreadManager.java
--- src/java/org/apache/excalibur/event/command/TPCThreadManager.java   2 Oct 
2002 01:46:57 -0000       1.32
+++ src/java/org/apache/excalibur/event/command/TPCThreadManager.java   23 Nov 
2002 12:28:50 -0000
@@ -53,6 +53,7 @@
 import org.apache.avalon.framework.parameters.ParameterException;
 import org.apache.avalon.framework.parameters.Parameterizable;
 import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.excalibur.thread.ThreadControl;
 import org.apache.excalibur.util.SystemUtil;
 
 /**
@@ -147,7 +148,15 @@
     public final void dispose()
     {
         super.dispose();
-
+       // We should dispose all active threads
+       ThreadControl[] threads = getThreadControls();
+       for (int i=0;i<threads.length;i++) 
+       {
+           if ( !threads[i].isFinished() ) 
+           {
+               m_tpool.dispose(threads[i]);
+           }
+       }
         m_tpool.dispose();
     }
 }
Index: src/java/org/apache/excalibur/event/command/EventThreadPool.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon-excalibur/event/src/java/org/apache/excalibur/event/command/EventThreadPool.java,v
retrieving revision 1.5
diff -u -r1.5 EventThreadPool.java
--- src/java/org/apache/excalibur/event/command/EventThreadPool.java    18 Oct 
2002 02:22:39 -0000      1.5
+++ src/java/org/apache/excalibur/event/command/EventThreadPool.java    23 Nov 
2002 12:29:15 -0000
@@ -135,16 +135,16 @@
 
     protected void releaseWorker( final WorkerThread worker )
     {
-        try
-        {
-            worker.interrupted();
-            m_pool.release( worker );
+       worker.interrupted();
+       if (m_pool != null)
+       {
+           m_pool.release( worker );
         }
-        catch( Throwable e )
-        {
-            // trying to figure out why a NullPointer exeception can occur ...
-            System.err.println( "Unexpected condition while releasing worker: 
" + worker );
-            e.printStackTrace();
+       else
+       {
+            System.err.println( "ThreadPool disposed before workerThread has 
finished. Please call dispose(Worker) before." + worker );
+           Thread.currentThread().dumpStack();
+
         }
     }
 }
Index: src/java/org/apache/excalibur/fortress/container/AbstractContainer.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon-excalibur/fortress/src/java/org/apache/excalibur/fortress/container/AbstractContainer.java,v
retrieving revision 1.20
diff -u -r1.20 AbstractContainer.java
--- src/java/org/apache/excalibur/fortress/container/AbstractContainer.java     
12 Nov 2002 04:05:08 -0000      1.20
+++ src/java/org/apache/excalibur/fortress/container/AbstractContainer.java     
23 Nov 2002 12:49:22 -0000
@@ -67,6 +67,8 @@
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.commons.collections.BoundedFifoBuffer;
+import org.apache.commons.collections.Buffer;
+import org.apache.commons.collections.BufferUtils;
 import org.apache.commons.collections.StaticBucketMap;
 import org.apache.excalibur.container.lifecycle.LifecycleExtensionManager;
 import org.apache.excalibur.event.Queue;
@@ -113,6 +115,8 @@
     protected List m_components = new ArrayList( 10 );
     protected LifecycleExtensionManager m_extManager;
 
+    private Buffer m_prepareHandlerCommands;
+
     /**
      * Pull the manager items from the context so we can use them to set up
      * the system.
@@ -454,7 +458,8 @@
     {
         final Iterator i = m_components.iterator();
         final BoundedFifoBuffer buffer = new BoundedFifoBuffer( 
m_components.size() );
-
+       m_prepareHandlerCommands = new BoundedFifoBuffer( m_components.size() );
+       
         while( i.hasNext() )
         {
             try
@@ -468,7 +473,8 @@
                         final PrepareHandlerCommand element =
                             new PrepareHandlerCommand( handler, getLogger() );
                         m_commandQueue.enqueue( element );
-                    }
+                       m_prepareHandlerCommands.add( element );
+                   }
                     else
                     {
                         handler.prepareHandler();
@@ -506,19 +512,37 @@
 
             throw new Exception( message.toString() );
         }
+                                           
     }
 
+    private void disablePrepareHandlerCommands() {
+       if ( m_prepareHandlerCommands == null)
+       {
+           return;
+       }
+       while ( !m_prepareHandlerCommands.isEmpty() ) 
+       {
+           ( (PrepareHandlerCommand) m_prepareHandlerCommands.remove() 
).disable();
+       }
+           
+    }
+    
     /**
      * Disposes of all components and frees resources that they consume.
      */
     public void dispose()
     {
+       disablePrepareHandlerCommands();
         final Iterator i = m_components.iterator();
         while( i.hasNext() )
         {
             final ComponentHandlerEntry entry = 
(ComponentHandlerEntry)i.next();
             final ComponentHandler handler = entry.getHandler();
-            ContainerUtil.dispose( handler );
+           if (handler instanceof LEAwareComponentHandler) 
+           {
+               ContainerUtil.dispose( ((LEAwareComponentHandler) handler 
).getDelegate() );
+           } 
+           ContainerUtil.dispose( handler );
         }
     }
 
@@ -532,4 +556,5 @@
     {
         return m_serviceManager;
     }
-}
\ No newline at end of file
+
+}
Index: 
src/java/org/apache/excalibur/fortress/handler/LEAwareComponentHandler.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon-excalibur/fortress/src/java/org/apache/excalibur/fortress/handler/LEAwareComponentHandler.java,v
retrieving revision 1.4
diff -u -r1.4 LEAwareComponentHandler.java
--- src/java/org/apache/excalibur/fortress/handler/LEAwareComponentHandler.java 
9 Nov 2002 23:25:44 -0000       1.4
+++ src/java/org/apache/excalibur/fortress/handler/LEAwareComponentHandler.java 
23 Nov 2002 12:49:29 -0000
@@ -124,4 +124,11 @@
         }
         m_componentHandler.put( component );
     }
+
+    /**
+       returns the nested ComponentHandler 
+     */
+    public ComponentHandler getDelegate() {
+       return m_componentHandler;
+    }
 }
Index: 
src/java/org/apache/excalibur/fortress/container/commands/PrepareHandlerCommand.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon-excalibur/fortress/src/java/org/apache/excalibur/fortress/container/commands/PrepareHandlerCommand.java,v
retrieving revision 1.3
diff -u -r1.3 PrepareHandlerCommand.java
--- 
src/java/org/apache/excalibur/fortress/container/commands/PrepareHandlerCommand.java
        10 Nov 2002 12:00:17 -0000      1.3
+++ 
src/java/org/apache/excalibur/fortress/container/commands/PrepareHandlerCommand.java
        23 Nov 2002 12:49:37 -0000
@@ -64,6 +64,7 @@
 {
     private final ComponentHandler m_handler;
     private final Logger m_logger;
+    private boolean m_disabled;
 
     public PrepareHandlerCommand( final ComponentHandler handler,
                                   final Logger logger )
@@ -75,7 +76,12 @@
     public void execute()
         throws Exception
     {
-        try
+       if ( m_disabled )
+       {
+           return;
+       }
+
+       try
         {
             m_handler.prepareHandler();
         }
@@ -88,6 +94,15 @@
 
             throw e;
         }
+    }
+    
+    /**
+       prevent execution of command (if already executed).
+     */
+    public void disable() 
+    {
+
+       m_disabled = true;
     }
 }
 
Index: src/java/org/apache/excalibur/fortress/lookup/FortressServiceManager.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon-excalibur/fortress/src/java/org/apache/excalibur/fortress/lookup/FortressServiceManager.java,v
retrieving revision 1.25
diff -u -r1.25 FortressServiceManager.java
--- src/java/org/apache/excalibur/fortress/lookup/FortressServiceManager.java   
9 Nov 2002 23:38:39 -0000       1.25
+++ src/java/org/apache/excalibur/fortress/lookup/FortressServiceManager.java   
21 Nov 2002 16:18:11 -0000
@@ -141,7 +141,15 @@
 
     public boolean hasService( final String key )
     {
-        return m_container.has( key, null );
+       boolean hasService = m_container.has( key, null );
+        if ( ( !hasService ) && ( m_parent != null ) )
+       {
+           return m_parent.hasService( key );
+       } 
+        else 
+       {
+           return hasService;
+       }
     }
 
     public void release( final Object component )

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to