Skip to content

Commit

Permalink
refactor ProcessFactory to help debugging (#191)
Browse files Browse the repository at this point in the history
  • Loading branch information
xu-chiheng authored Dec 6, 2022
1 parent 9114ac3 commit ac64d4a
Showing 1 changed file with 173 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@
* QNX Software Systems - Initial API and implementation
* Martin Oberhuber (Wind River) - [303083] Split out the Spawner
* Red Hat Inc. - add flatpak support
* 徐持恒 Xu Chiheng - refactor to help debugging
*******************************************************************************/
package org.eclipse.cdt.utils.spawner;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.TreeMap;

import org.eclipse.cdt.internal.core.natives.CNativePlugin;
import org.eclipse.cdt.internal.core.natives.Messages;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;

/**
* @noextend This class is not intended to be subclassed by clients.
Expand All @@ -33,6 +40,106 @@ public class ProcessFactory {
private boolean hasSpawner;
private Runtime runtime;

private String[] modifyCmdArrayIfFlatpak(String[] cmdarray) {
if (System.getenv("FLATPAK_SANDBOX_DIR") != null) { //$NON-NLS-1$
String[] newArray = new String[cmdarray.length + 3];
System.arraycopy(cmdarray, 0, newArray, 3, cmdarray.length);
newArray[0] = "flatpak-spawn"; //$NON-NLS-1$
newArray[1] = "--host"; //$NON-NLS-1$
newArray[2] = "--watch-bus"; //$NON-NLS-1$
cmdarray = newArray;
}
return cmdarray;
}

private static TreeMap<String, String> newEmptyEnvironment() {
TreeMap<String, String> environment;
if (Platform.getOS().equals(Platform.OS_WIN32)) {
environment = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
} else {
environment = new TreeMap<>();
}
return environment;
}

private static TreeMap<String, String> envpToEnvMap(String[] envp) {
TreeMap<String, String> environment = newEmptyEnvironment();
if (envp != null) {
for (String envstring : envp) {
int eqlsign = envstring.indexOf('=');
if (eqlsign != -1) {
environment.put(envstring.substring(0, eqlsign), envstring.substring(eqlsign + 1));
} else {
// Silently ignore envstrings lacking the required `='.
}
}
}
return environment;
}

private static TreeMap<String, String> getDefaultEnvironment() {
TreeMap<String, String> environment = newEmptyEnvironment();
Map<String, String> env = new ProcessBuilder().environment();
environment.putAll(env);
return environment;
}

private static void appendEnvMapComparison(StringBuilder sb, TreeMap<String, String> environmentA,
TreeMap<String, String> environmentB) {
TreeMap<String, String> environmentC = newEmptyEnvironment();
environmentC.putAll(environmentA);
environmentC.putAll(environmentB);
Iterator<Entry<String, String>> iterator = environmentC.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
String key = entry.getKey();
String valueA, valueB;
if (environmentA.containsKey(key)) {
valueA = environmentA.get(key);
if (environmentB.containsKey(key)) {
valueB = environmentB.get(key);
int result = valueA.compareTo(valueB);
if (result == 0) {
// not changed
sb.append(' ');
sb.append(key);
sb.append('=');
sb.append(valueA);
sb.append('\n');
} else {
// changed
sb.append('-');
sb.append(key);
sb.append('=');
sb.append(valueA);
sb.append('\n');
sb.append('+');
sb.append(key);
sb.append('=');
sb.append(valueB);
sb.append('\n');
}
} else {
// removed
sb.append('-');
sb.append(key);
sb.append('=');
sb.append(valueA);
sb.append('\n');
}
} else {
// environmentB contains the key
valueB = environmentB.get(key);
// added
sb.append('+');
sb.append(key);
sb.append('=');
sb.append(valueB);
sb.append('\n');
}
}
}

private class Builder {
String[] cmdarray;
String[] envp;
Expand All @@ -50,13 +157,15 @@ public Builder(String cmd) throws IOException {
this.cmdarray = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++)
this.cmdarray[i] = st.nextToken();
this.cmdarray = modifyCmdArrayIfFlatpak(this.cmdarray);
}

public Builder(String[] cmdarray) throws IOException {
if (cmdarray.length == 0 || cmdarray[0].isEmpty()) {
throw new IllegalArgumentException("Empty command"); //$NON-NLS-1$
}
this.cmdarray = cmdarray;
this.cmdarray = modifyCmdArrayIfFlatpak(this.cmdarray);
}

public Builder environment(String[] envp) {
Expand All @@ -81,8 +190,71 @@ public Builder gracefulExitTimeMs(int gracefulExitTimeMs) {
return this;
}

private StringBuilder debug() {
// for debug purpose
StringBuilder sb = new StringBuilder();

sb.append("command :\n"); //$NON-NLS-1$
for (int i = 0; i < cmdarray.length; i++) {
sb.append(i);
sb.append(" : \""); //$NON-NLS-1$
sb.append(cmdarray[i]);
sb.append("\"\n"); //$NON-NLS-1$
}
sb.append("\n\n"); //$NON-NLS-1$

sb.append("directory :\n"); //$NON-NLS-1$
if (dir != null) {
String pathString = dir.toString();
sb.append(pathString);
sb.append('\n');
Path path = new Path(pathString);
String pathDevice = path.getDevice();
String[] pathSegments = path.segments();
if (pathDevice != null) {
sb.append("device : "); //$NON-NLS-1$
sb.append(pathDevice);
sb.append('\n');
}
sb.append("segments : \n"); //$NON-NLS-1$
for (int i = 0; i < pathSegments.length; i++) {
sb.append(i);
sb.append(" : "); //$NON-NLS-1$
sb.append(pathSegments[i]);
sb.append('\n');
}
} else {
sb.append("not specified\n"); //$NON-NLS-1$
}
sb.append("\n\n"); //$NON-NLS-1$

{
TreeMap<String, String> environmentA = getDefaultEnvironment();
TreeMap<String, String> environmentB = envpToEnvMap(envp);

sb.append("environment :\n"); //$NON-NLS-1$
appendEnvMapComparison(sb, environmentA, environmentB);
sb.append("\n\n"); //$NON-NLS-1$
}
if (use_pty) {
sb.append("use pty : "); //$NON-NLS-1$
sb.append(pty.toString());
sb.append("\n\n"); //$NON-NLS-1$
}
if (has_gracefulExitTimeMs) {
sb.append("has gracefulExitTimeMs : "); //$NON-NLS-1$
sb.append(gracefulExitTimeMs);
sb.append("\n\n"); //$NON-NLS-1$
}
// set breakpoint on next line to inspect sb when debugging, to see the
// ultimate parameters of ProcessBuilder
return sb;
}

public Process start() throws IOException {
cmdarray = modifyCmdArrayIfFlatpak(cmdarray);
// Uncomment the next line, set a breakpoint in the last line of debug() method,
// when the breakpoint is triggered, inspect the sb variable to see detailed info on what is being launched.
// debug();
Process p;
if (hasSpawner) {
if (use_pty) {
Expand Down Expand Up @@ -215,16 +387,4 @@ public Process exec(String cmdarray[], String[] envp, File dir, PTY pty, int gra
.gracefulExitTimeMs(gracefulExitTimeMs).start();
return p;
}

private String[] modifyCmdArrayIfFlatpak(String[] cmdarray) {
if (System.getenv("FLATPAK_SANDBOX_DIR") != null) { //$NON-NLS-1$
String[] newArray = new String[cmdarray.length + 3];
System.arraycopy(cmdarray, 0, newArray, 3, cmdarray.length);
newArray[0] = "flatpak-spawn"; //$NON-NLS-1$
newArray[1] = "--host"; //$NON-NLS-1$
newArray[2] = "--watch-bus"; //$NON-NLS-1$
cmdarray = newArray;
}
return cmdarray;
}
}

0 comments on commit ac64d4a

Please sign in to comment.