Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epankou/bug strace kill orphaned processes ewc 421 #177

Merged
merged 15 commits into from
Jan 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
243 changes: 131 additions & 112 deletions daemon/src/org/eclipse/iofog/command_line/util/CommandShellExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,116 +34,135 @@
* on 2/7/18.
*/
public class CommandShellExecutor {
private static final String MODULE_NAME = "CommandShellExecutor";
private static final String CMD = "/bin/sh";
private static final String CMD_WIN = "powershell";


public static CommandShellResultSet<List<String>, List<String>> executeCommand(String command) {
String[] fullCommand = computeCommand(command);
return execute(fullCommand);
}

public static CommandShellResultSet<List<String>, List<String>> executeScript(String script, String... args) {
String[] fullCommand = computeScript(script, args);
return execute(fullCommand);
}

public static void executeDynamicCommand(String command, CommandShellResultSet<List<String>, List<String>> resultSet, AtomicBoolean isRun) {
String[] fullCommand = computeCommand(command);
executeDynamic(fullCommand, resultSet, isRun);
}

private static CommandShellResultSet<List<String>, List<String>> execute( String[] fullCommand) {
CommandShellResultSet<List<String>, List<String>> resultSet = null;
try {
Process process = Runtime.getRuntime().exec(fullCommand);
List<String> value = readOutput(process, Process::getInputStream);
List<String> errors = readOutput(process, Process::getErrorStream);
resultSet = new CommandShellResultSet<>(value, errors);
} catch (IOException e) {
LoggingService.logWarning(MODULE_NAME, e.getMessage());
}
return resultSet;
}

private static void executeDynamic( String[] fullCommand, CommandShellResultSet<List<String>, List<String>> resultSet, AtomicBoolean isRun) {
try {
Process process = Runtime.getRuntime().exec(fullCommand);

Runnable readVal = () -> {
readOutputDynamic(process, Process::getInputStream, resultSet.getValue(), isRun);
};
new Thread(readVal).start();

Runnable readErr = () -> {
readOutputDynamic(process, Process::getErrorStream, resultSet.getError(), isRun);
};
new Thread(readErr).start();

} catch (IOException e) {
LoggingService.logWarning(MODULE_NAME, e.getMessage());
}
}


public static <V, E> CommandShellResultSet<V, E> executeCommand(String command, Function<CommandShellResultSet<List<String>, List<String>>, CommandShellResultSet<V, E>> mapper) {
return executeCommand(command).map(mapper);
}

private static String[] computeCommand(String command) {
return new String[]{
SystemUtils.IS_OS_WINDOWS ? CMD_WIN : CMD,
"-c",
command
};
}

private static String[] computeScript(String script, String... args) {
String[] command = {
SystemUtils.IS_OS_WINDOWS ? CMD_WIN : CMD,
script
};

Stream<String> s1 = Arrays.stream(command);
Stream<String> s2 = Arrays.stream(args);
return Stream.concat(s1, s2).toArray(String[]::new);
}

private static List<String> readOutput(Process process, Function<Process, InputStream> streamExtractor) throws IOException {
List<String> result = new ArrayList<>();
String line;
try (BufferedReader stdInput = new BufferedReader(new
InputStreamReader(streamExtractor.apply(process), UTF_8))) {
while ((line = stdInput.readLine()) != null) {
result.add(line);
}
}
return result;
}

private static void readOutputDynamic(Process process, Function<Process,
InputStream> streamExtractor, List<String> result,
AtomicBoolean isRun) {
String line;
if (result == null) {
return;
}
try (BufferedReader stdInput = new BufferedReader(new
InputStreamReader(streamExtractor.apply(process)))) {

while (isRun != null && isRun.get()) {
line = stdInput.readLine();
if (line != null) {
result.add(line);
} else {
Thread.sleep(3000);
}
}
} catch (InterruptedException | IOException e) {
LoggingService.logWarning(MODULE_NAME, e.getMessage());
} finally {
process.destroy();
}
}
private static final String MODULE_NAME = "CommandShellExecutor";
private static final String CMD = "/bin/sh";
private static final String CMD_WIN = "powershell";


public static CommandShellResultSet<List<String>, List<String>> executeCommand(String command) {
String[] fullCommand = computeCommand(command);
return execute(fullCommand);
}

public static CommandShellResultSet<List<String>, List<String>> executeScript(String script, String... args) {
String[] fullCommand = computeScript(script, args);
return execute(fullCommand);
}

public static void executeDynamicCommand(String command,
CommandShellResultSet<List<String>, List<String>> resultSet,
AtomicBoolean isRun,
Runnable killOrphanedProcessesRunnable) {
String[] fullCommand = computeCommand(command);
executeDynamic(fullCommand, resultSet, isRun, killOrphanedProcessesRunnable);
}

private static CommandShellResultSet<List<String>, List<String>> execute(String[] fullCommand) {
CommandShellResultSet<List<String>, List<String>> resultSet = null;
try {
Process process = Runtime.getRuntime().exec(fullCommand);
List<String> value = readOutput(process, Process::getInputStream);
List<String> errors = readOutput(process, Process::getErrorStream);
resultSet = new CommandShellResultSet<>(value, errors);
} catch (IOException e) {
LoggingService.logWarning(MODULE_NAME, e.getMessage());
}
return resultSet;
}

private static void executeDynamic(String[] fullCommand,
CommandShellResultSet<List<String>, List<String>> resultSet,
AtomicBoolean isRun,
Runnable killOrphanedProcessesRunnable) {
try {
Process process = Runtime.getRuntime().exec(fullCommand);

Runnable readVal = () -> {
readOutputDynamic(process, Process::getInputStream, resultSet.getValue(), isRun, killOrphanedProcessesRunnable);
};
new Thread(readVal).start();

Runnable readErr = () -> {
readOutputDynamic(process, Process::getErrorStream, resultSet.getError(), isRun, killOrphanedProcessesRunnable);
};
new Thread(readErr).start();

} catch (IOException e) {
LoggingService.logWarning(MODULE_NAME, e.getMessage());
}
}


public static <V, E> CommandShellResultSet<V, E> executeCommand(String command, Function<CommandShellResultSet<List<String>, List<String>>, CommandShellResultSet<V, E>> mapper) {
return executeCommand(command).map(mapper);
}

private static String[] computeCommand(String command) {
return new String[]{
SystemUtils.IS_OS_WINDOWS ? CMD_WIN : CMD,
"-c",
command
};
}

private static String[] computeScript(String script, String... args) {
String[] command = {
SystemUtils.IS_OS_WINDOWS ? CMD_WIN : CMD,
script
};

Stream<String> s1 = Arrays.stream(command);
Stream<String> s2 = Arrays.stream(args);
return Stream.concat(s1, s2).toArray(String[]::new);
}

private static List<String> readOutput(Process process, Function<Process, InputStream> streamExtractor) throws IOException {
List<String> result = new ArrayList<>();
String line;
try (BufferedReader stdInput = new BufferedReader(new
InputStreamReader(streamExtractor.apply(process), UTF_8))) {
while ((line = stdInput.readLine()) != null) {
result.add(line);
}
}
return result;
}

private static void readOutputDynamic(Process process,
Function<Process, InputStream> streamExtractor,
List<String> result,
AtomicBoolean isRun,
Runnable killOrphanedProcessesRunnable) {
StringBuilder line = new StringBuilder();
if (result == null) {
return;
}
try (BufferedReader reader = new BufferedReader(new
InputStreamReader(streamExtractor.apply(process)))) {

while (isRun != null && isRun.get()) {
if (reader.ready()) {
int c = reader.read();
if (c == -1) {
break;
}
if (System.lineSeparator().contains(Character.toString((char)c)) && line.length() != 0) {
result.add(line.toString());
line.setLength(0);
} else {
line.append((char)c);
}
} else {
Thread.sleep(3000);
}
}
} catch (InterruptedException | IOException e) {
LoggingService.logWarning(MODULE_NAME, e.getMessage());
} finally {
process.destroy();
if (killOrphanedProcessesRunnable != null) {
killOrphanedProcessesRunnable.run();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,21 @@ private int getPidByMicroserviceUuid(String microserviceUuid) throws IllegalArgu
private void runStrace(MicroserviceStraceData microserviceStraceData) {
String straceCommand = "strace -p " + microserviceStraceData.getPid();
CommandShellResultSet<List<String>, List<String>> resultSet = new CommandShellResultSet<>(null, microserviceStraceData.getResultBuffer());
CommandShellExecutor.executeDynamicCommand(straceCommand, resultSet, microserviceStraceData.getStraceRun());
CommandShellExecutor.executeDynamicCommand(
straceCommand,
resultSet,
microserviceStraceData.getStraceRun(),
killOrphanedStraceProcessesRunnable()
);
}

private Runnable killOrphanedStraceProcessesRunnable() {
return () -> {
CommandShellResultSet<List<String>, List<String>> resultSet = CommandShellExecutor.executeCommand("pgrep strace");
if (resultSet.getValue() != null) {
resultSet.getValue().forEach(value -> CommandShellExecutor.executeCommand(String.format("kill -9 %s", value)));
}
};
}

}