/** Launch process and waits until it's down */
  public void launch(Monitored mp) {
    if (!lifecycle.tryToMoveTo(Lifecycle.State.STARTING)) {
      throw new IllegalStateException("Already started");
    }
    monitored = mp;

    try {
      LoggerFactory.getLogger(getClass()).info("Starting " + getKey());
      Runtime.getRuntime().addShutdownHook(shutdownHook);
      stopWatcher.start();

      monitored.start();
      boolean ready = false;
      while (!ready) {
        ready = monitored.isReady();
        Thread.sleep(20L);
      }

      // notify monitor that process is ready
      commands.setReady();

      if (lifecycle.tryToMoveTo(Lifecycle.State.STARTED)) {
        monitored.awaitStop();
      }
    } catch (Exception e) {
      LoggerFactory.getLogger(getClass()).warn("Fail to start " + getKey(), e);

    } finally {
      stop();
    }
  }
 @Override
 public void stopAsync() {
   if (lifecycle.tryToMoveTo(Lifecycle.State.STOPPING)) {
     stopperThread =
         new StopperThread(
             monitored,
             commands,
             Long.parseLong(props.nonNullValue(PROPERTY_TERMINATION_TIMEOUT)));
     stopperThread.start();
     stopWatcher.stopWatching();
   }
 }