aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/windows')
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java47
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java11
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/jni/BUILD37
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java (renamed from src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java)8
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java (renamed from src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java)8
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java (renamed from src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java)132
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/runfiles/BUILD16
-rw-r--r--src/main/java/com/google/devtools/build/lib/windows/runfiles/WindowsRunfiles.java (renamed from src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java)4
9 files changed, 183 insertions, 81 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
index e1eb08fc3b..83707d24d4 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
@@ -24,6 +24,7 @@ import com.google.devtools.build.lib.vfs.JavaIoFileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Path.PathFactory;
import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
index 0aea491bd3..59d9792696 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.windows;
import com.google.devtools.build.lib.shell.Subprocess;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -57,7 +58,7 @@ public class WindowsSubprocess implements Subprocess {
*
* <p>This class is non-static for debugging purposes.
*/
- private class ProcessInputStream extends InputStream {
+ private static final class ProcessInputStream extends InputStream {
private long nativeStream;
ProcessInputStream(long nativeStream) {
@@ -75,18 +76,18 @@ public class WindowsSubprocess implements Subprocess {
}
@Override
- public synchronized int read(byte b[], int off, int len) throws IOException {
+ public synchronized int read(byte[] b, int off, int len) throws IOException {
if (nativeStream == WindowsProcesses.INVALID) {
throw new IllegalStateException();
}
- int result = WindowsProcesses.nativeReadStream(nativeStream, b, off, len);
+ int result = WindowsProcesses.readStream(nativeStream, b, off, len);
if (result == 0) {
return -1; // EOF
}
if (result == -1) {
- throw new IOException(WindowsProcesses.nativeStreamGetLastError(nativeStream));
+ throw new IOException(WindowsProcesses.streamGetLastError(nativeStream));
}
return result;
@@ -95,7 +96,7 @@ public class WindowsSubprocess implements Subprocess {
@Override
public synchronized void close() {
if (nativeStream != WindowsProcesses.INVALID) {
- WindowsProcesses.nativeCloseStream(nativeStream);
+ WindowsProcesses.closeStream(nativeStream);
nativeStream = WindowsProcesses.INVALID;
}
}
@@ -107,7 +108,7 @@ public class WindowsSubprocess implements Subprocess {
}
}
- private static AtomicInteger THREAD_SEQUENCE_NUMBER = new AtomicInteger(1);
+ private static final AtomicInteger THREAD_SEQUENCE_NUMBER = new AtomicInteger(1);
private static final ExecutorService WAITER_POOL = Executors.newCachedThreadPool(
new ThreadFactory() {
@Override
@@ -134,13 +135,9 @@ public class WindowsSubprocess implements Subprocess {
this.nativeProcess = nativeProcess;
this.timeoutMillis = timeoutMillis;
stdoutStream =
- stdoutRedirected
- ? null
- : new ProcessInputStream(WindowsProcesses.nativeGetStdout(nativeProcess));
+ stdoutRedirected ? null : new ProcessInputStream(WindowsProcesses.getStdout(nativeProcess));
stderrStream =
- stderrRedirected
- ? null
- : new ProcessInputStream(WindowsProcesses.nativeGetStderr(nativeProcess));
+ stderrRedirected ? null : new ProcessInputStream(WindowsProcesses.getStderr(nativeProcess));
stdinStream = new ProcessOutputStream();
waitLatch = new CountDownLatch(1);
// Every Windows process we start consumes a thread here. This is suboptimal, but seems to be
@@ -150,7 +147,7 @@ public class WindowsSubprocess implements Subprocess {
}
private void waiterThreadFunc() {
- switch (WindowsProcesses.nativeWaitFor(nativeProcess, timeoutMillis)) {
+ switch (WindowsProcesses.waitFor(nativeProcess, timeoutMillis)) {
case 0:
// Excellent, process finished in time.
break;
@@ -158,15 +155,15 @@ public class WindowsSubprocess implements Subprocess {
case 1:
// Timeout. Terminate the process if we can.
timedout.set(true);
- WindowsProcesses.nativeTerminate(nativeProcess);
+ WindowsProcesses.terminate(nativeProcess);
break;
case 2:
// Error. There isn't a lot we can do -- the process is still alive but
// WaitForMultipleObjects() failed for some odd reason. We'll pretend it terminated and
// log a message to jvm.out .
- System.err.println("Waiting for process "
- + WindowsProcesses.nativeGetProcessPid(nativeProcess) + " failed");
+ System.err.println(
+ "Waiting for process " + WindowsProcesses.getProcessPid(nativeProcess) + " failed");
break;
}
@@ -184,20 +181,15 @@ public class WindowsSubprocess implements Subprocess {
@Override
public synchronized boolean destroy() {
checkLiveness();
-
- if (!WindowsProcesses.nativeTerminate(nativeProcess)) {
- return false;
- }
-
- return true;
+ return WindowsProcesses.terminate(nativeProcess);
}
@Override
public synchronized int exitValue() {
checkLiveness();
- int result = WindowsProcesses.nativeGetExitCode(nativeProcess);
- String error = WindowsProcesses.nativeProcessGetLastError(nativeProcess);
+ int result = WindowsProcesses.getExitCode(nativeProcess);
+ String error = WindowsProcesses.processGetLastError(nativeProcess);
if (!error.isEmpty()) {
throw new IllegalStateException(error);
}
@@ -227,7 +219,7 @@ public class WindowsSubprocess implements Subprocess {
stderrStream.close();
long process = nativeProcess;
nativeProcess = WindowsProcesses.INVALID;
- WindowsProcesses.nativeDeleteProcess(process);
+ WindowsProcesses.deleteProcess(process);
}
}
@@ -252,12 +244,11 @@ public class WindowsSubprocess implements Subprocess {
int remaining = len;
int currentOffset = off;
while (remaining != 0) {
- int written = WindowsProcesses.nativeWriteStdin(
- nativeProcess, b, currentOffset, remaining);
+ int written = WindowsProcesses.writeStdin(nativeProcess, b, currentOffset, remaining);
// I think the Windows API never returns 0 in dwNumberOfBytesWritten
// Verify.verify(written != 0);
if (written == -1) {
- throw new IOException(WindowsProcesses.nativeProcessGetLastError(nativeProcess));
+ throw new IOException(WindowsProcesses.processGetLastError(nativeProcess));
}
remaining -= written;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
index e85325dcaa..e398a3b195 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
@@ -19,6 +19,7 @@ import com.google.devtools.build.lib.shell.Subprocess;
import com.google.devtools.build.lib.shell.SubprocessBuilder;
import com.google.devtools.build.lib.shell.SubprocessBuilder.StreamAction;
import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import java.io.File;
import java.io.IOException;
import java.util.List;
@@ -37,11 +38,9 @@ public class WindowsSubprocessFactory implements Subprocess.Factory {
@Override
public Subprocess create(SubprocessBuilder builder) throws IOException {
- WindowsJniLoader.loadJni();
-
List<String> argv = builder.getArgv();
- // DO NOT quote argv0, nativeCreateProcess will do it for us.
+ // DO NOT quote argv0, createProcess will do it for us.
String argv0 = processArgv0(argv.get(0));
String argvRest =
argv.size() > 1 ? WindowsProcesses.quoteCommandLine(argv.subList(1, argv.size())) : "";
@@ -51,11 +50,11 @@ public class WindowsSubprocessFactory implements Subprocess.Factory {
String stderrPath = getRedirectPath(builder.getStderr(), builder.getStderrFile());
long nativeProcess =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
argv0, argvRest, env, builder.getWorkingDirectory().getPath(), stdoutPath, stderrPath);
- String error = WindowsProcesses.nativeProcessGetLastError(nativeProcess);
+ String error = WindowsProcesses.processGetLastError(nativeProcess);
if (!error.isEmpty()) {
- WindowsProcesses.nativeDeleteProcess(nativeProcess);
+ WindowsProcesses.deleteProcess(nativeProcess);
throw new IOException(error);
}
diff --git a/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD b/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD
new file mode 100644
index 0000000000..ed8ca69799
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD
@@ -0,0 +1,37 @@
+package(
+ default_visibility = [
+ "//src/main/java/com/google/devtools/build/lib:__subpackages__",
+ "//src/test/java/com/google/devtools/build/lib:__subpackages__",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
+
+java_library(
+ name = "jni",
+ exports = [
+ ":file",
+ ":processes",
+ ],
+)
+
+java_library(
+ name = "file",
+ srcs = ["WindowsFileOperations.java"],
+ deps = [":jni-loader"],
+)
+
+java_library(
+ name = "processes",
+ srcs = ["WindowsProcesses.java"],
+ deps = [":jni-loader"],
+)
+
+java_library(
+ name = "jni-loader",
+ srcs = ["WindowsJniLoader.java"],
+ deps = ["//src/main/java/com/google/devtools/build/lib/windows/runfiles"],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
index 0d68c36db8..44b6cba976 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
import java.io.IOException;
@@ -49,11 +49,11 @@ public class WindowsFileOperations {
private static final int IS_JUNCTION_NO = 1;
private static final int IS_JUNCTION_ERROR = 2;
- static native int nativeIsJunction(String path, String[] error);
+ private static native int nativeIsJunction(String path, String[] error);
- static native boolean nativeGetLongPath(String path, String[] result, String[] error);
+ private static native boolean nativeGetLongPath(String path, String[] result, String[] error);
- static native boolean nativeCreateJunction(String name, String target, String[] error);
+ private static native boolean nativeCreateJunction(String name, String target, String[] error);
/** Determines whether `path` is a junction point or directory symlink. */
public static boolean isJunction(String path) throws IOException {
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
index bc59eacca4..8b53d0c1a8 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
@@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
+import com.google.devtools.build.lib.windows.runfiles.WindowsRunfiles;
import java.io.IOException;
-/**
- * Loads native code under Windows.
- */
+/** Loads native code under Windows. */
public class WindowsJniLoader {
private static boolean jniLoaded = false;
+
public static synchronized void loadJni() {
if (jniLoaded) {
return;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
index 9aac2a7719..1eaab25904 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
@@ -12,13 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
import java.util.List;
-/**
- * Process management on Windows.
- */
+/** Process management on Windows. */
public class WindowsProcesses {
public static final long INVALID = -1;
@@ -27,11 +25,6 @@ public class WindowsProcesses {
}
/**
- * returns the PID of the current process.
- */
- static native int nativeGetpid();
-
- /**
* Creates a process with the specified Windows command line.
*
* <p>Appropriately quoting arguments is the responsibility of the caller.
@@ -50,7 +43,13 @@ public class WindowsProcesses {
* work.
* @return the opaque identifier of the created process
*/
- static native long nativeCreateProcess(
+ public static long createProcess(
+ String argv0, String argvRest, byte[] env, String cwd, String stdoutFile, String stderrFile) {
+ WindowsJniLoader.loadJni();
+ return nativeCreateProcess(argv0, argvRest, env, cwd, stdoutFile, stderrFile);
+ }
+
+ private static native long nativeCreateProcess(
String argv0, String argvRest, byte[] env, String cwd, String stdoutFile, String stderrFile);
/**
@@ -60,13 +59,28 @@ public class WindowsProcesses {
*
* @return the number of bytes written
*/
- static native int nativeWriteStdin(long process, byte[] bytes, int offset, int length);
+ public static int writeStdin(long process, byte[] bytes, int offset, int length) {
+ WindowsJniLoader.loadJni();
+ return nativeWriteStdin(process, bytes, offset, length);
+ }
+
+ private static native int nativeWriteStdin(long process, byte[] bytes, int offset, int length);
/** Returns an opaque identifier of stdout stream for the process. */
- static native long nativeGetStdout(long process);
+ public static long getStdout(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetStdout(process);
+ }
+
+ private static native long nativeGetStdout(long process);
- /** Returns am opaque identifier of stderr stream for the process. */
- static native long nativeGetStderr(long process);
+ /** Returns an opaque identifier of stderr stream for the process. */
+ public static long getStderr(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetStderr(process);
+ }
+
+ private static native long nativeGetStderr(long process);
/**
* Reads data from the stream into the given array. {@code stream} should come from {@link
@@ -76,34 +90,55 @@ public class WindowsProcesses {
*
* @return the number of bytes read, 0 on EOF, or -1 if there was an error.
*/
- static native int nativeReadStream(long stream, byte[] bytes, int offset, int length);
+ public static int readStream(long stream, byte[] bytes, int offset, int length) {
+ WindowsJniLoader.loadJni();
+ return nativeReadStream(stream, bytes, offset, length);
+ }
+
+ private static native int nativeReadStream(long stream, byte[] bytes, int offset, int length);
/**
* Waits until the given process terminates. If timeout is non-negative, it indicates the number
* of milliseconds before the call times out.
*
* <p>Return values:
- * <li>0: Process finished</li>
- * <li>1: Timeout</li>
- * <li>2: Something went wrong</li>
+ * <li>0: Process finished
+ * <li>1: Timeout
+ * <li>2: Something went wrong
*/
- static native int nativeWaitFor(long process, long timeout);
+ public static int waitFor(long process, long timeout) {
+ WindowsJniLoader.loadJni();
+ return nativeWaitFor(process, timeout);
+ }
- /**
- * Returns the exit code of the process. Throws {@code IllegalStateException} if something
- * goes wrong.
- */
- static native int nativeGetExitCode(long process);
+ private static native int nativeWaitFor(long process, long timeout);
/**
- * Returns the process ID of the given process or -1 if there was an error.
+ * Returns the exit code of the process. Throws {@code IllegalStateException} if something goes
+ * wrong.
*/
- static native int nativeGetProcessPid(long process);
+ public static int getExitCode(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetExitCode(process);
+ }
- /**
- * Terminates the given process. Returns true if the termination was successful.
- */
- static native boolean nativeTerminate(long process);
+ private static native int nativeGetExitCode(long process);
+
+ /** Returns the process ID of the given process or -1 if there was an error. */
+ public static int getProcessPid(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetProcessPid(process);
+ }
+
+ private static native int nativeGetProcessPid(long process);
+
+ /** Terminates the given process. Returns true if the termination was successful. */
+ public static boolean terminate(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeTerminate(process);
+ }
+
+ private static native boolean nativeTerminate(long process);
/**
* Releases the native data structures associated with the process.
@@ -111,7 +146,12 @@ public class WindowsProcesses {
* <p>Calling any other method on the same process after this call will result in the JVM crashing
* or worse.
*/
- static native void nativeDeleteProcess(long process);
+ public static void deleteProcess(long process) {
+ WindowsJniLoader.loadJni();
+ nativeDeleteProcess(process);
+ }
+
+ private static native void nativeDeleteProcess(long process);
/**
* Closes the stream
@@ -119,7 +159,12 @@ public class WindowsProcesses {
* @param stream should come from {@link #nativeGetStdout(long)} or {@link
* #nativeGetStderr(long)}.
*/
- static native void nativeCloseStream(long stream);
+ public static void closeStream(long stream) {
+ WindowsJniLoader.loadJni();
+ nativeCloseStream(stream);
+ }
+
+ private static native void nativeCloseStream(long stream);
/**
* Returns a string representation of the last error caused by any call on the given process or
@@ -130,16 +175,29 @@ public class WindowsProcesses {
* <p>After this call returns, subsequent calls will return the empty string if there was no
* failed operation in between.
*/
- static native String nativeProcessGetLastError(long process);
+ public static String processGetLastError(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeProcessGetLastError(process);
+ }
- static native String nativeStreamGetLastError(long process);
+ private static native String nativeProcessGetLastError(long process);
+ public static String streamGetLastError(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeStreamGetLastError(process);
+ }
+
+ private static native String nativeStreamGetLastError(long process);
+
+ /** returns the PID of the current process. */
public static int getpid() {
WindowsJniLoader.loadJni();
return nativeGetpid();
}
- static String quoteCommandLine(List<String> argv) {
+ private static native int nativeGetpid();
+
+ public static String quoteCommandLine(List<String> argv) {
StringBuilder result = new StringBuilder();
for (int iArg = 0; iArg < argv.size(); iArg++) {
if (iArg != 0) {
@@ -170,8 +228,8 @@ public class WindowsProcesses {
} else {
// Backslashes everywhere else are quoted if they are followed by a
// quote or a backslash
- result.append(arg.charAt(iChar + 1) == '"' || arg.charAt(iChar + 1) == '\\'
- ? "\\\\" : "\\");
+ result.append(
+ arg.charAt(iChar + 1) == '"' || arg.charAt(iChar + 1) == '\\' ? "\\\\" : "\\");
}
break;
default:
diff --git a/src/main/java/com/google/devtools/build/lib/windows/runfiles/BUILD b/src/main/java/com/google/devtools/build/lib/windows/runfiles/BUILD
new file mode 100644
index 0000000000..1ec264d53f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/windows/runfiles/BUILD
@@ -0,0 +1,16 @@
+package(
+ default_visibility = [
+ "//src/main/java/com/google/devtools/build/lib:__subpackages__",
+ "//src/test/java/com/google/devtools/build/lib:__subpackages__",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
+
+java_library(
+ name = "runfiles",
+ srcs = ["WindowsRunfiles.java"],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java b/src/main/java/com/google/devtools/build/lib/windows/runfiles/WindowsRunfiles.java
index 876531073a..bf0d131259 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/runfiles/WindowsRunfiles.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.runfiles;
import java.io.BufferedReader;
import java.io.FileInputStream;
@@ -59,7 +59,7 @@ public final class WindowsRunfiles {
}
runfiles.put(splitLine[0], splitLine[1]);
- }
+ }
}
}
}