public void launchProcess()

in genie-agent/src/main/java/com/netflix/genie/agent/execution/process/impl/JobProcessManagerImpl.java [87:164]


    public void launchProcess(
        final File jobDirectory,
        final File jobScript,
        final boolean interactive,
        @Nullable final Integer timeout,
        final boolean launchInJobDirectory
    ) throws JobLaunchException {
        if (!this.launched.compareAndSet(false, true)) {
            throw new IllegalStateException("Job already launched");
        }

        this.isInteractiveMode = interactive;

        final ProcessBuilder processBuilder = new ProcessBuilder();

        // Validate job running directory
        if (jobDirectory == null) {
            throw new JobLaunchException("Job directory is null");
        } else if (!jobDirectory.exists()) {
            throw new JobLaunchException("Job directory does not exist: " + jobDirectory);
        } else if (!jobDirectory.isDirectory()) {
            throw new JobLaunchException("Job directory is not a directory: " + jobDirectory);
        } else if (!jobDirectory.canWrite()) {
            throw new JobLaunchException("Job directory is not writable: " + jobDirectory);
        }

        if (jobScript == null) {
            throw new JobLaunchException("Job script is null");
        } else if (!jobScript.exists() || !jobScript.isFile()) {
            throw new JobLaunchException("Job script is not a valid file");
        } else if (!jobScript.canExecute()) {
            throw new JobLaunchException("Job script is not executable");
        }

        this.initFailedFileRef.set(PathUtils.jobSetupErrorMarkerFilePath(jobDirectory).toFile());

        log.info("Executing job script: {} (working directory: {})",
            jobScript.getAbsolutePath(),
            launchInJobDirectory ? jobDirectory : Paths.get("").toAbsolutePath().normalize().toString());

        processBuilder.command(jobScript.getAbsolutePath());

        if (launchInJobDirectory) {
            processBuilder.directory(jobDirectory);
        }

        if (interactive) {
            processBuilder.inheritIO();
        } else {
            processBuilder.redirectError(PathUtils.jobStdErrPath(jobDirectory).toFile());
            processBuilder.redirectOutput(PathUtils.jobStdOutPath(jobDirectory).toFile());
        }

        final Span currentSpan = this.tracer.currentSpan();
        if (currentSpan != null) {
            processBuilder.environment().putAll(this.tracePropagator.injectForJob(currentSpan.context()));
        }

        if (this.killed.get()) {
            log.info("Job aborted, skipping launch");
            return;
        }
        log.info("Launching job");
        try {
            this.processReference.set(processBuilder.start());
            if (timeout != null) {
                // NOTE: There is a chance of a SLIGHT delay here between the process launch and the timeout
                final Instant timeoutInstant = Instant.now().plusSeconds(timeout);
                this.timeoutKillThread.set(
                    this.taskScheduler.schedule(new TimeoutKiller(this), timeoutInstant)
                );
                log.info("Scheduled timeout kill to occur {} second(s) from now at {}", timeout, timeoutInstant);
            }
        } catch (IOException | SecurityException e) {
            throw new JobLaunchException("Failed to launch job: ", e);
        }
        log.info("Process launched (pid: {})", this.getPid(this.processReference.get()));
    }