From e131e3cef7357a2f5acdc3d86979b8c5486ca71b Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 20 Mar 2012 11:19:25 +0000
Subject: [PATCH] Fix OPENDJ-457: Sleeping replication threads prevent server from shutting down

---
 opends/src/server/org/opends/server/replication/service/HeartbeatMonitor.java |   55 ++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/opends/src/server/org/opends/server/replication/service/HeartbeatMonitor.java b/opends/src/server/org/opends/server/replication/service/HeartbeatMonitor.java
index d2325c8..6345f48 100644
--- a/opends/src/server/org/opends/server/replication/service/HeartbeatMonitor.java
+++ b/opends/src/server/org/opends/server/replication/service/HeartbeatMonitor.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2007-2009 Sun Microsystems, Inc.
- *      Portions Copyright 2011 ForgeRock AS
+ *      Portions Copyright 2011-2012 ForgeRock AS
  */
 
 package org.opends.server.replication.service;
@@ -31,10 +31,10 @@
 import static org.opends.messages.ReplicationMessages.*;
 import static org.opends.server.loggers.ErrorLogger.logError;
 import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
 
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.replication.protocol.ProtocolSession;
+import org.opends.server.types.DebugLogLevel;
 
 import org.opends.server.api.DirectoryThread;
 
@@ -70,9 +70,10 @@
 
 
   /**
-   * Set this to stop the thread.
+   * Thread life-cycle state.
    */
   private volatile boolean shutdown = false;
+  private final Object shutdownLock = new Object();
 
 
 
@@ -110,7 +111,11 @@
    */
   public void shutdown()
   {
-    shutdown = true;
+    synchronized (shutdownLock)
+    {
+      shutdown = true;
+      shutdownLock.notifyAll();
+    }
   }
 
   /**
@@ -119,27 +124,30 @@
   @Override
   public void run()
   {
-    boolean gotOneFailure = false;
     if (debugEnabled())
     {
       TRACER.debugInfo(this + " is starting, expected interval is " +
                 heartbeatInterval);
     }
+
     try
     {
+      boolean gotOneFailure = false;
       while (!shutdown)
       {
         long now = System.currentTimeMillis();
         long lastReceiveTime = session.getLastReceiveTime();
         if (now > lastReceiveTime + heartbeatInterval)
         {
-          if (gotOneFailure == true)
+          if (gotOneFailure)
           {
             // Heartbeat is well overdue so the server is assumed to be dead.
             logError(WARN_HEARTBEAT_FAILURE.get(serverID,
-                replicationServerID,
-                session.getReadableRemoteAddress(), baseDN));
-            session.close();
+                replicationServerID, session.getReadableRemoteAddress(),
+                baseDN));
+
+            // Exit monitor and close session.
+            shutdown = true;
             break;
           }
           else
@@ -151,13 +159,26 @@
         {
           gotOneFailure = false;
         }
-        try
+
+        // Sleep.
+        synchronized (shutdownLock)
         {
-          Thread.sleep(heartbeatInterval);
-        }
-        catch (InterruptedException e)
-        {
-          // That's OK.
+          if (!shutdown)
+          {
+            try
+            {
+              shutdownLock.wait(heartbeatInterval);
+            }
+            catch (InterruptedException e)
+            {
+              // Server shutdown monitor may interrupt slow threads.
+              if (debugEnabled())
+              {
+                TRACER.debugCaught(DebugLogLevel.ERROR, e);
+              }
+              shutdown = true;
+            }
+          }
         }
       }
     }
@@ -165,9 +186,9 @@
     {
       if (debugEnabled())
       {
-        TRACER.debugInfo("Heartbeat monitor is exiting." +
-            stackTraceToSingleLineString(new Exception()));
+        TRACER.debugInfo("Heartbeat monitor is exiting");
       }
+      session.close();
     }
   }
 }

--
Gitblit v1.10.0