This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-base.git

commit 6f5771acf4b943840c477a8621e54c43a3497b97
Author: Robert Munteanu <[email protected]>
AuthorDate: Wed Aug 8 12:40:03 2018 +0300

    SLING-7811 - NPE when repository is starting up
    
    Make the repository initialisation and startup process more robust
    against restarts.
    
    It is possible that while a the repository startup is happening in an
    async manner in the "Apache Sling Repository Startup Thread" a stop is
    requested. This thread should be notified of any stop requests and
    gracefully handle the shutdown.
---
 .../jcr/base/AbstractSlingRepositoryManager.java   | 31 +++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java 
b/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java
index bdbdcbc..bedb9e7 100644
--- 
a/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java
+++ 
b/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java
@@ -23,6 +23,7 @@ import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.jcr.Repository;
 
@@ -109,6 +110,10 @@ public abstract class AbstractSlingRepositoryManager {
 
     private final Object repoInitLock = new Object();
 
+    private volatile Thread startupThread;
+
+    private volatile boolean stopRequested;
+
     /**
      * Returns the default workspace, which may be <code>null</code> meaning to
      * use the repository provided default workspace.
@@ -447,17 +452,20 @@ public abstract class AbstractSlingRepositoryManager {
         // start repository asynchronously to allow LoginAdminWhitelist to 
become available
         // NOTE: making this conditional allows tests to register a mock 
whitelist before
         // activating the RepositoryManager, so they don't need to deal with 
async startup
-        new Thread("Apache Sling Repository Startup Thread") {
+        startupThread = new Thread("Apache Sling Repository Startup Thread") {
             @Override
             public void run() {
                 try {
                     waitForWhitelist.await();
                     initializeAndRegisterRepositoryService();
                 } catch (InterruptedException e) {
-                    throw new RuntimeException("Interrupted while waiting for 
LoginAdminWhitelist", e);
+                    log.info("Interrupted while waiting for the {} service, 
cancelling repository initialisation", 
LoginAdminWhitelist.class.getSimpleName(), e);
+                    Thread.currentThread().interrupt();
+                    return;
                 }
             }
-        }.start();
+        };
+        startupThread.start();
     }
 
     private boolean isRepositoryServiceRegistered() {
@@ -474,6 +482,11 @@ public abstract class AbstractSlingRepositoryManager {
                 // ensure we really have the repository
                 log.debug("start: got a Repository");
                 this.repository = newRepo;
+                if ( stopRequested ) {
+                    log.debug("Stop requested, cancelling initialisation and 
stopping repository");
+                    stop();
+                    return;
+                }
                 synchronized ( this.repoInitLock ) {
                     this.masterSlingRepository = 
this.create(this.bundleContext.getBundle());
 
@@ -547,6 +560,18 @@ public abstract class AbstractSlingRepositoryManager {
      */
     protected final void stop() {
 
+        stopRequested = true;
+        if ( startupThread != null && startupThread != Thread.currentThread() 
) {
+            try {
+                startupThread.interrupt();
+                startupThread.join();
+            } catch (InterruptedException e) {
+                log.debug("Interrupted while waiting for the " + 
startupThread.getName() + " to complete.", e);
+                Thread.currentThread().interrupt();
+            }
+            startupThread = null;
+        }
+
         // ensure the repository is really disposed off
         if (repository != null || isRepositoryServiceRegistered()) {
             log.info("stop: Repository still running, forcing shutdown");

Reply via email to