Windows, JNI: WaitableProcess supports inv. HANDLE
WaitableProcess and AutoAttributeList support
INVALID_HANDLE_VALUE for some or all of the std_*
handles of the subprocess.
AutoAttributeList initializes the inheritable
HANDLE array only for the valid HANDLEs.
WaitableProcess forbids HANDLE inheritance if all
std_* handles are invalid.
Closes #8115.
PiperOrigin-RevId: 244844487
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD
index fa0e7e0..ee22122 100644
--- a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD
@@ -25,7 +25,7 @@
"//third_party:jsr305",
"//third_party:jsr330_inject",
"//third_party:junit4",
- "//third_party:mockito2",
+ "//third_party:mockito",
"//third_party:truth",
],
)
diff --git a/src/main/native/windows/process.cc b/src/main/native/windows/process.cc
index 48e54bc..7aa6092 100644
--- a/src/main/native/windows/process.cc
+++ b/src/main/native/windows/process.cc
@@ -130,7 +130,7 @@
/* lpCommandLine */ mutable_commandline.get(),
/* lpProcessAttributes */ NULL,
/* lpThreadAttributes */ NULL,
- /* bInheritHandles */ TRUE,
+ /* bInheritHandles */ attr_list->InheritAnyHandles() ? TRUE : FALSE,
/* dwCreationFlags */ CREATE_NO_WINDOW // Don't create console
// window
| CREATE_NEW_PROCESS_GROUP // So that Ctrl-Break isn't propagated
diff --git a/src/main/native/windows/util.cc b/src/main/native/windows/util.cc
index f3182c2..829fd5c 100644
--- a/src/main/native/windows/util.cc
+++ b/src/main/native/windows/util.cc
@@ -73,12 +73,20 @@
bool AutoAttributeList::Create(HANDLE stdin_h, HANDLE stdout_h, HANDLE stderr_h,
std::unique_ptr<AutoAttributeList>* result,
wstring* error_msg) {
+ if (stdin_h == INVALID_HANDLE_VALUE && stdout_h == INVALID_HANDLE_VALUE &&
+ stderr_h == INVALID_HANDLE_VALUE) {
+ result->reset(new AutoAttributeList());
+ return true;
+ }
+
static constexpr DWORD kAttributeCount = 1;
SIZE_T size = 0;
// According to MSDN, the first call to InitializeProcThreadAttributeList is
// expected to fail.
InitializeProcThreadAttributeList(NULL, kAttributeCount, 0, &size);
+ SetLastError(ERROR_SUCCESS);
+
std::unique_ptr<uint8_t[]> data(new uint8_t[size]);
LPPROC_THREAD_ATTRIBUTE_LIST attrs =
reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(data.get());
@@ -94,10 +102,11 @@
std::unique_ptr<AutoAttributeList> attr_list(
new AutoAttributeList(std::move(data), stdin_h, stdout_h, stderr_h));
- if (!UpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
- attr_list->handles_.handle_array,
- StdHandles::kHandleCount * sizeof(HANDLE),
- NULL, NULL)) {
+ if (!UpdateProcThreadAttribute(
+ attrs, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
+ attr_list->handles_.ValidHandles(),
+ attr_list->handles_.ValidHandlesCount() * sizeof(HANDLE), NULL,
+ NULL)) {
if (error_msg) {
DWORD err = GetLastError();
*error_msg = MakeErrorMessage(WSTR(__FILE__), __LINE__,
@@ -109,14 +118,40 @@
return true;
}
+AutoAttributeList::StdHandles::StdHandles()
+ : valid_handles_(0),
+ stdin_h_(INVALID_HANDLE_VALUE),
+ stdout_h_(INVALID_HANDLE_VALUE),
+ stderr_h_(INVALID_HANDLE_VALUE) {
+ valid_handle_array_[0] = INVALID_HANDLE_VALUE;
+ valid_handle_array_[1] = INVALID_HANDLE_VALUE;
+ valid_handle_array_[2] = INVALID_HANDLE_VALUE;
+}
+
+AutoAttributeList::StdHandles::StdHandles(HANDLE stdin_h, HANDLE stdout_h,
+ HANDLE stderr_h)
+ : valid_handles_(0),
+ stdin_h_(stdin_h),
+ stdout_h_(stdout_h),
+ stderr_h_(stderr_h) {
+ valid_handle_array_[0] = INVALID_HANDLE_VALUE;
+ valid_handle_array_[1] = INVALID_HANDLE_VALUE;
+ valid_handle_array_[2] = INVALID_HANDLE_VALUE;
+ if (stdin_h != INVALID_HANDLE_VALUE) {
+ valid_handle_array_[valid_handles_++] = stdin_h;
+ }
+ if (stdout_h != INVALID_HANDLE_VALUE) {
+ valid_handle_array_[valid_handles_++] = stdout_h;
+ }
+ if (stderr_h != INVALID_HANDLE_VALUE) {
+ valid_handle_array_[valid_handles_++] = stderr_h;
+ }
+}
+
AutoAttributeList::AutoAttributeList(std::unique_ptr<uint8_t[]>&& data,
HANDLE stdin_h, HANDLE stdout_h,
HANDLE stderr_h)
- : data_(std::move(data)) {
- handles_.stdin_h = stdin_h;
- handles_.stdout_h = stdout_h;
- handles_.stderr_h = stderr_h;
-}
+ : data_(std::move(data)), handles_(stdin_h, stdout_h, stderr_h) {}
AutoAttributeList::~AutoAttributeList() {
DeleteProcThreadAttributeList(*this);
@@ -129,21 +164,25 @@
void AutoAttributeList::InitStartupInfoExA(STARTUPINFOEXA* startup_info) const {
ZeroMemory(startup_info, sizeof(STARTUPINFOEXA));
startup_info->StartupInfo.cb = sizeof(STARTUPINFOEXA);
- startup_info->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
- startup_info->StartupInfo.hStdInput = handles_.stdin_h;
- startup_info->StartupInfo.hStdOutput = handles_.stdout_h;
- startup_info->StartupInfo.hStdError = handles_.stderr_h;
- startup_info->lpAttributeList = *this;
+ if (InheritAnyHandles()) {
+ startup_info->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+ startup_info->StartupInfo.hStdInput = handles_.StdIn();
+ startup_info->StartupInfo.hStdOutput = handles_.StdOut();
+ startup_info->StartupInfo.hStdError = handles_.StdErr();
+ startup_info->lpAttributeList = *this;
+ }
}
void AutoAttributeList::InitStartupInfoExW(STARTUPINFOEXW* startup_info) const {
ZeroMemory(startup_info, sizeof(STARTUPINFOEXW));
startup_info->StartupInfo.cb = sizeof(STARTUPINFOEXW);
- startup_info->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
- startup_info->StartupInfo.hStdInput = handles_.stdin_h;
- startup_info->StartupInfo.hStdOutput = handles_.stdout_h;
- startup_info->StartupInfo.hStdError = handles_.stderr_h;
- startup_info->lpAttributeList = *this;
+ if (InheritAnyHandles()) {
+ startup_info->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+ startup_info->StartupInfo.hStdInput = handles_.StdIn();
+ startup_info->StartupInfo.hStdOutput = handles_.StdOut();
+ startup_info->StartupInfo.hStdError = handles_.StdErr();
+ startup_info->lpAttributeList = *this;
+ }
}
static void QuotePath(const wstring& path, wstring* result) {
diff --git a/src/main/native/windows/util.h b/src/main/native/windows/util.h
index 1cd2dab..2766017 100644
--- a/src/main/native/windows/util.h
+++ b/src/main/native/windows/util.h
@@ -66,26 +66,36 @@
class AutoAttributeList {
public:
+ AutoAttributeList() {}
+
static bool Create(HANDLE stdin_h, HANDLE stdout_h, HANDLE stderr_h,
std::unique_ptr<AutoAttributeList>* result,
- wstring* error_msg = nullptr);
+ std::wstring* error_msg = nullptr);
~AutoAttributeList();
+ bool InheritAnyHandles() const { return handles_.ValidHandlesCount() > 0; }
+
void InitStartupInfoExA(STARTUPINFOEXA* startup_info) const;
void InitStartupInfoExW(STARTUPINFOEXW* startup_info) const;
private:
- struct StdHandles {
- static constexpr size_t kHandleCount = 3;
- union {
- HANDLE handle_array[kHandleCount];
- struct {
- HANDLE stdin_h;
- HANDLE stdout_h;
- HANDLE stderr_h;
- };
- };
+ class StdHandles {
+ public:
+ StdHandles();
+ StdHandles(HANDLE stdin_h, HANDLE stdout_h, HANDLE stderr_h);
+ size_t ValidHandlesCount() const { return valid_handles_; }
+ HANDLE* ValidHandles() { return valid_handle_array_; }
+ HANDLE StdIn() const { return stdin_h_; }
+ HANDLE StdOut() const { return stdout_h_; }
+ HANDLE StdErr() const { return stderr_h_; }
+
+ private:
+ size_t valid_handles_;
+ HANDLE valid_handle_array_[3];
+ HANDLE stdin_h_;
+ HANDLE stdout_h_;
+ HANDLE stderr_h_;
};
AutoAttributeList(std::unique_ptr<uint8_t[]>&& data, HANDLE stdin_h,