Hi devs,
Right now there’s a problem when XWiki is shutdown. This is what currently happens:
2014-09-23 13:54:05,563 [Thread-1] DEBUG o.x.shutdown - Starting XWiki
shutdown...
2014-09-23 13:54:05,563 [Thread-1] DEBUG o.x.shutdown - Stopping
Database Connection Pool...
2014-09-23 13:54:05,735 [Thread-1] DEBUG o.x.shutdown - Database
Connection Pool has been stopped
2014-09-23 13:54:10,513 [Thread-1] DEBUG o.x.shutdown - Stopping
component [org.xwiki.localization.wiki.internal.DocumentTranslationBundleFactory]…
2014-09-23 13:54:10,513 [Thread-1] DEBUG o.x.shutdown - Component
[org.xwiki.localization.wiki.internal.DocumentTranslationBundleFactory] has been stopped
…
2014-09-23 13:54:10,514 [Thread-1] DEBUG o.x.shutdown - Stopping
component [org.xwiki.search.solr.internal.DefaultSolrIndexer]...
2014-09-23 13:54:10,514 [Thread-1] DEBUG o.x.shutdown - Component
[org.xwiki.search.solr.internal.DefaultSolrIndexer] has been stopped
…
2014-09-23 13:54:10,539 [Thread-1] INFO o.x.shutdown - XWiki shutdown
has been completed.
As you can see the problem is that the DB is stopped first. So any code accessing the DB
will get an error once the connection pool is stopped. This is why we get a lot stack
traces when you ctrl-c XWiki quickly after it starts (i.e. when the init is not finished
or when SOLR is still indexing). You can also get stack traces if a watchlist is being
sent or some scheduler job is executing for example.
There are 2 ways to fix this:
- solution 1: all code that accesses the DB could check if an XWiki shutdown is in
progress and don’t generate stack traces if this is the case
- solution 2: stop the DB as the last thing, after everything else has stopped
Obviously solution 2 is much better.
I’ve started implementing it by doing this:
- Remove the current HibernateShutdownEventListener since this is executed first during
shutdown, before component disposal
- Instead have XWikiHibernateStore implement Disposable and move the content of
HibernateShutdownEventListener in that method
This works already better but it’s not enough since ECM.dispose() works out the component
dependencies but this works only for explicit dependencies and doesn’t work if a component
uses the ComponentManager to dynamically find implementations (as this is the case for
example for DefaultSolrIndexer).
Thus in order to help the component disposal process, I propose to introduce a new
annotation: @DisposePriority(int).
Note that an alternative would be to introduce a new Disposable interface with a new
getPriority() method in it (we cannot modify the current Disposable since that would break
backward compat).
The idea is then to use this information in ECM.dispose() to first sort all components
based on this and then only to order them with their dependencies.
WDYT?
Thanks
-Vincent