public boolean start(Supplier<ManagedProcess> commandLauncher) {
    if (!lifecycle.tryToMoveTo(ManagedProcessLifecycle.State.STARTING)) {
      // has already been started
      return false;
    }
    try {
      this.process = commandLauncher.get();
    } catch (RuntimeException e) {
      LOG.error("Failed to launch process [{}]", processId.getHumanReadableName(), e);
      lifecycle.tryToMoveTo(ManagedProcessLifecycle.State.STOPPING);
      finalizeStop();
      throw e;
    }
    this.stdOutGobbler = new StreamGobbler(process.getInputStream(), appSettings, processId.getKey());
    this.stdOutGobbler.start();
    this.stdErrGobbler = new StreamGobbler(process.getErrorStream(), appSettings, processId.getKey());
    this.stdErrGobbler.start();
    this.stopWatcher.start();
    this.eventWatcher.start();
    // Could be improved by checking the status "up" in shared memory.
    // Not a problem so far as this state is not used by listeners.
    lifecycle.tryToMoveTo(ManagedProcessLifecycle.State.STARTED);
    return true;
  }
@Test
  public void process_requests_are_listened_on_regular_basis() {
    ManagedProcessEventListener listener = mock(ManagedProcessEventListener.class);
    ManagedProcessHandler underTest = newHanderBuilder(A_PROCESS_ID)
      .addEventListener(listener)
      .setWatcherDelayMs(1L)
      .build();

    try (TestManagedProcess testProcess = new TestManagedProcess()) {
      underTest.start(() -> testProcess);

      testProcess.operational = true;

      verify(listener, timeout(1_000L)).onManagedProcessEvent(A_PROCESS_ID, ManagedProcessEventListener.Type.OPERATIONAL);
    }
  }