@@ -1,19 +1,47 @@
 import logging
 import subprocess
 import thread
+import time
+import threading
 
-from haproxy.config import HAPROXY_RUN_COMMAND
+from haproxy.config import HAPROXY_RUN_COMMAND, RELOAD_TIMEOUT
 
 logger = logging.getLogger("haproxy")
 
+# RELOAD_TIMEOUT has the following values and effect:
+# -1 : Reload haproxy with "-st" which will immediately kill the previous process
+# 0 : Reload haproxy with "-sf" and no timeout.  This can potentially leave 
+#     "broken" processes (where the backends have changed) hanging around 
+#     with existing connections.
+# > 0 : Reload haproxy with "-sf" but if it takes longer than RELOAD_TIMEOUT then kill it
+#       This gives existing connections a chance to finish.  RELOAD_TIMEOUT should be set to 
+#       the approximate time it takes docker to finish updating services.  By this point the
+#       existing configuration will be invalid, and any connections still using it will 
+#       have invalid backends.
+#
+def run_reload(old_process, timeout = int(RELOAD_TIMEOUT)):
 
-def run_reload(old_process):
     if old_process:
         # Reload haproxy
         logger.info("Reloading HAProxy")
-        new_process = subprocess.Popen(HAPROXY_RUN_COMMAND + ["-sf", str(old_process.pid)])
-        thread.start_new_thread(wait_pid, (old_process,))
-        logger.info("HAProxy has been reloaded(PID: %s)", str(new_process.pid))
+        if timeout == -1:
+          flag = "-st"
+          logging.info("Restarting HAProxy immediately")
+        else:
+          flag = "-sf"
+          logging.info("Restarting HAProxy gracefully")
+        
+        new_process = subprocess.Popen(HAPROXY_RUN_COMMAND + [flag, str(old_process.pid)])
+        logger.info("HAProxy is reloading (new PID: %s)", str(new_process.pid))
+        
+        thread = threading.Thread(target = wait_pid, args=[old_process,timeout])
+        thread.start()
+
+        # Block only if we have a timeout.  If we don't it could take forever, and so
+        # returning immediately maintains the original behaviour of no timeout.
+        if timeout > 0:
+          thread.join()
+
     else:
         # Launch haproxy
         logger.info("Launching HAProxy")
@@ -23,6 +51,28 @@ def run_reload(old_process):
     return new_process
 
 
-def wait_pid(process):
+def wait_pid(process, timeout):
+    start = time.time()
+
+    if timeout > 0:
+      timer = threading.Timer(timeout, timeout_handler, [process] )
+      timer.start()
+
     process.wait()
-    logger.info("HAProxy(PID:%s) has been terminated" % str(process.pid))
+
+    if timer is not None:
+      timer.cancel();
+
+    duration = time.time() - start
+    logger.info("Old HAProxy(PID: %s) ended after %s sec", str(process.pid), str(duration))
+
+      
+def timeout_handler( processs ):
+  if processs.poll() is None:
+    try:
+      processs.terminate()
+      logger.info("Old HAProxy process taking too long to complete - terminating")
+    except OSError as e:
+      if e.errno != errno.ESRCH:
+        raise
+  