All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hubspot.singularity.runner.base.shared.ProcessUtils Maven / Gradle / Ivy

There is a newer version: 1.5.0
Show newest version
package com.hubspot.singularity.runner.base.shared;

import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;

import javax.annotation.Nullable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Charsets;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.io.CharStreams;
import com.google.common.io.Closeables;
import com.hubspot.mesos.JavaUtils;

public class ProcessUtils {

  private static final Logger LOG = LoggerFactory.getLogger(ProcessUtils.class);

  private final Optional log;

  public ProcessUtils() {
    this(null);
  }

  public ProcessUtils(@Nullable Logger log) {
    this.log = Optional.fromNullable(log);
  }

  public static class ProcessResult {

    private final int exitCode;
    private final String output;

    public ProcessResult(int exitCode, String output) {
      this.exitCode = exitCode;
      this.output = output;
    }

    public int getExitCode() {
      return exitCode;
    }

    public String getOutput() {
      return output;
    }

    @Override
    public String toString() {
      return "ProcessResult [exitCode=" + exitCode + ", output=" + output + "]";
    }

  }

  public ProcessResult sendSignal(Signal signal, int pid) {
    final long start = System.currentTimeMillis();

    if (log.isPresent()) {
      final String logLine = String.format("Signaling %s (%s) to process %s", signal, signal.getCode(), pid);
      if (signal == Signal.CHECK) {
        log.get().trace(logLine);
      } else {
        log.get().info(logLine);
      }
    }

    if (signal != Signal.CHECK) {
      LOG.debug("Signaling {} ({}) to process {}", signal, signal.getCode(), pid);
    }

    try {
      final ProcessBuilder pb = new ProcessBuilder("kill", String.format("-%s", signal.getCode()), Integer.toString(pid));
      pb.redirectErrorStream(true);

      final Process p = pb.start();

      final int exitCode = p.waitFor();

      final String output = CharStreams.toString(new InputStreamReader(p.getInputStream(), Charsets.UTF_8));

      Closeables.closeQuietly(p.getInputStream());

      if (log.isPresent()) {
        log.get().trace("Kill signal process for {} got exit code {} after {}", pid, exitCode, JavaUtils.duration(start));
      }

      return new ProcessResult(exitCode, output.trim());
    } catch (InterruptedException | IOException e) {
      throw Throwables.propagate(e);
    }
  }

  public int getUnixPID(Process process) {
    Preconditions.checkArgument(process.getClass().getName().equals("java.lang.UNIXProcess"));

    Class clazz = process.getClass();

    try {
      Field field = clazz.getDeclaredField("pid");
      field.setAccessible(true);
      Object pidObject = field.get(process);
      return (Integer) pidObject;
    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
      throw Throwables.propagate(e);
    }
  }

  public boolean doesProcessExist(int pid) {
    ProcessResult processResult = sendSignal(Signal.CHECK, pid);
    if (processResult.getExitCode() != 0 && processResult.output.contains("No such process")) {
      return false;
    }
    return true;
  }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy