Make sure task_runner.stop() is idempotent (clean up only once).
diff --git a/mysos/executor/mysos_task_runner.py b/mysos/executor/mysos_task_runner.py
index 0051bcb..eb75076 100644
--- a/mysos/executor/mysos_task_runner.py
+++ b/mysos/executor/mysos_task_runner.py
@@ -148,6 +148,15 @@
     self._exited.set()
 
   def stop(self, timeout=10):
+    with self._lock:
+      # stop() could be called by multiple threads. Locking so we only stop the runner once.
+      if self._stopping:
+        log.warn("The runner is already stopping/stopped")
+        return False
+      else:
+        log.info("Stopping runner")
+        self._stopping = True
+
     try:
       return self._stop(timeout)
     finally:
@@ -163,17 +172,10 @@
       :return: True if an active runner is stopped, False if the runner is not started or already
                stopping/stopped.
     """
-    if not self._started:
-      log.warn("Cannot stop the runner because it's not started")
-      return False
-
-    if self._stopping:
-      log.warn("The runner is already stopping/stopped")
-      return False
-
     with self._lock:
-      log.info("Stopping runner")
-      self._stopping = True
+      if not self._started:
+        log.warn("Cannot stop the runner because it's not started")
+        return False
 
       if not self._popen:
         log.info("The runner task did not start successfully so no need to kill it")
@@ -198,6 +200,8 @@
         except OSError as e:
           log.info("The sub-processes are already terminated: %s" % e)
           return False
+    else:
+      return True
 
     log.info("Waiting for process to terminate due to SIGKILL")
     if not self._exited.wait(timeout=timeout):