Skip to content

Commit d235a06

Browse files
laszlocsomorCopybara-Service
authored andcommitted
Windows, JNI: AutoAttributeList owns HANDLE array
Also in this commit: - AutoAttributeList can initialize a STARTUPINFOEX structure (both A and W) Closes #6758. PiperOrigin-RevId: 222818516
1 parent b2fbb03 commit d235a06

4 files changed

Lines changed: 65 additions & 31 deletions

File tree

src/main/cpp/blaze_util_windows.cc

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -690,23 +690,16 @@ int ExecuteDaemon(const string& exe,
690690
// Create an attribute list.
691691
wstring werror;
692692
std::unique_ptr<AutoAttributeList> lpAttributeList;
693-
HANDLE handlesToInherit[3] = {devnull, stdout_file, stderr_handle};
694-
if (!AutoAttributeList::Create(handlesToInherit, 3, &lpAttributeList,
695-
&werror)) {
693+
if (!AutoAttributeList::Create(devnull, stdout_file, stderr_handle,
694+
&lpAttributeList, &werror)) {
696695
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
697696
<< "ExecuteDaemon(" << exe << "): attribute list creation failed: "
698697
<< blaze_util::WstringToString(werror);
699698
}
700699

701700
PROCESS_INFORMATION processInfo = {0};
702701
STARTUPINFOEXA startupInfoEx = {0};
703-
704-
startupInfoEx.StartupInfo.cb = sizeof(startupInfoEx);
705-
startupInfoEx.StartupInfo.hStdInput = devnull;
706-
startupInfoEx.StartupInfo.hStdOutput = stdout_file;
707-
startupInfoEx.StartupInfo.hStdError = stderr_handle;
708-
startupInfoEx.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
709-
startupInfoEx.lpAttributeList = *(lpAttributeList.get());
702+
lpAttributeList->InitStartupInfoExA(&startupInfoEx);
710703

711704
CmdLine cmdline;
712705
CreateCommandLine(&cmdline, exe, args_vector);

src/main/native/windows/util.cc

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ wstring GetLastErrorString(DWORD error_code) {
7070
return result;
7171
}
7272

73-
bool AutoAttributeList::Create(HANDLE* handles, size_t count,
73+
bool AutoAttributeList::Create(HANDLE stdin_h, HANDLE stdout_h, HANDLE stderr_h,
7474
std::unique_ptr<AutoAttributeList>* result,
7575
wstring* error_msg) {
7676
static constexpr DWORD kAttributeCount = 1;
@@ -79,7 +79,7 @@ bool AutoAttributeList::Create(HANDLE* handles, size_t count,
7979
// According to MSDN, the first call to InitializeProcThreadAttributeList is
8080
// expected to fail.
8181
InitializeProcThreadAttributeList(NULL, kAttributeCount, 0, &size);
82-
std::unique_ptr<uint8_t> data(new uint8_t[size]);
82+
std::unique_ptr<uint8_t[]> data(new uint8_t[size]);
8383
LPPROC_THREAD_ATTRIBUTE_LIST attrs =
8484
reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(data.get());
8585
if (!InitializeProcThreadAttributeList(attrs, kAttributeCount, 0, &size)) {
@@ -92,20 +92,31 @@ bool AutoAttributeList::Create(HANDLE* handles, size_t count,
9292
return false;
9393
}
9494

95+
std::unique_ptr<AutoAttributeList> attr_list(
96+
new AutoAttributeList(std::move(data), stdin_h, stdout_h, stderr_h));
9597
if (!UpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
96-
handles, count * sizeof(HANDLE), NULL, NULL)) {
98+
attr_list->handles_.handle_array,
99+
StdHandles::kHandleCount * sizeof(HANDLE),
100+
NULL, NULL)) {
97101
if (error_msg) {
98102
DWORD err = GetLastError();
99103
*error_msg = MakeErrorMessage(WSTR(__FILE__), __LINE__,
100104
L"UpdateProcThreadAttribute", L"", err);
101105
}
102106
return false;
103107
}
104-
result->reset(new AutoAttributeList(data.release()));
108+
*result = std::move(attr_list);
105109
return true;
106110
}
107111

108-
AutoAttributeList::AutoAttributeList(uint8_t* data) : data_(data) {}
112+
AutoAttributeList::AutoAttributeList(std::unique_ptr<uint8_t[]>&& data,
113+
HANDLE stdin_h, HANDLE stdout_h,
114+
HANDLE stderr_h)
115+
: data_(std::move(data)) {
116+
handles_.stdin_h = stdin_h;
117+
handles_.stdout_h = stdout_h;
118+
handles_.stderr_h = stderr_h;
119+
}
109120

110121
AutoAttributeList::~AutoAttributeList() {
111122
DeleteProcThreadAttributeList(*this);
@@ -115,6 +126,26 @@ AutoAttributeList::operator LPPROC_THREAD_ATTRIBUTE_LIST() const {
115126
return reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(data_.get());
116127
}
117128

129+
void AutoAttributeList::InitStartupInfoExA(STARTUPINFOEXA* startup_info) const {
130+
ZeroMemory(startup_info, sizeof(STARTUPINFOEXA));
131+
startup_info->StartupInfo.cb = sizeof(STARTUPINFOEXA);
132+
startup_info->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
133+
startup_info->StartupInfo.hStdInput = handles_.stdin_h;
134+
startup_info->StartupInfo.hStdOutput = handles_.stdout_h;
135+
startup_info->StartupInfo.hStdError = handles_.stderr_h;
136+
startup_info->lpAttributeList = *this;
137+
}
138+
139+
void AutoAttributeList::InitStartupInfoExW(STARTUPINFOEXW* startup_info) const {
140+
ZeroMemory(startup_info, sizeof(STARTUPINFOEXW));
141+
startup_info->StartupInfo.cb = sizeof(STARTUPINFOEXW);
142+
startup_info->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
143+
startup_info->StartupInfo.hStdInput = handles_.stdin_h;
144+
startup_info->StartupInfo.hStdOutput = handles_.stdout_h;
145+
startup_info->StartupInfo.hStdError = handles_.stderr_h;
146+
startup_info->lpAttributeList = *this;
147+
}
148+
118149
static void QuotePath(const wstring& path, wstring* result) {
119150
*result = wstring(L"\"") + path + L"\"";
120151
}

src/main/native/windows/util.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,37 @@ class AutoHandle {
6666

6767
class AutoAttributeList {
6868
public:
69-
static bool Create(HANDLE* handles, size_t count,
69+
static bool Create(HANDLE stdin_h, HANDLE stdout_h, HANDLE stderr_h,
7070
std::unique_ptr<AutoAttributeList>* result,
7171
wstring* error_msg = nullptr);
7272
~AutoAttributeList();
73-
operator LPPROC_THREAD_ATTRIBUTE_LIST() const;
73+
74+
void InitStartupInfoExA(STARTUPINFOEXA* startup_info) const;
75+
76+
void InitStartupInfoExW(STARTUPINFOEXW* startup_info) const;
7477

7578
private:
76-
AutoAttributeList(uint8_t* data);
79+
struct StdHandles {
80+
static constexpr size_t kHandleCount = 3;
81+
union {
82+
HANDLE handle_array[kHandleCount];
83+
struct {
84+
HANDLE stdin_h;
85+
HANDLE stdout_h;
86+
HANDLE stderr_h;
87+
};
88+
};
89+
};
90+
91+
AutoAttributeList(std::unique_ptr<uint8_t[]>&& data, HANDLE stdin_h,
92+
HANDLE stdout_h, HANDLE stderr_h);
7793
AutoAttributeList(const AutoAttributeList&) = delete;
7894
AutoAttributeList& operator=(const AutoAttributeList&) = delete;
95+
96+
operator LPPROC_THREAD_ATTRIBUTE_LIST() const;
97+
7998
std::unique_ptr<uint8_t[]> data_;
99+
StdHandles handles_;
80100
};
81101

82102
#define WSTR1(x) L##x

tools/test/windows/tw.cc

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,11 +1146,10 @@ bool StartSubprocess(const Path& path, const std::vector<const wchar_t*>& args,
11461146

11471147
// Create an attribute object that specifies which particular handles shall
11481148
// the subprocess inherit. We pass this object to CreateProcessW.
1149-
HANDLE handle_array[] = {devnull_read, pipe_write, pipe_write_dup};
11501149
std::unique_ptr<bazel::windows::AutoAttributeList> attr_list;
11511150
std::wstring werror;
1152-
if (!bazel::windows::AutoAttributeList::Create(handle_array, 3, &attr_list,
1153-
&werror)) {
1151+
if (!bazel::windows::AutoAttributeList::Create(
1152+
devnull_read, pipe_write, pipe_write_dup, &attr_list, &werror)) {
11541153
LogError(__LINE__, werror);
11551154
return false;
11561155
}
@@ -1185,16 +1184,7 @@ bool StartSubprocess(const Path& path, const std::vector<const wchar_t*>& args,
11851184

11861185
PROCESS_INFORMATION process_info;
11871186
STARTUPINFOEXW startup_info;
1188-
ZeroMemory(&startup_info, sizeof(STARTUPINFOEXW));
1189-
startup_info.StartupInfo.cb = sizeof(STARTUPINFOEXW);
1190-
startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
1191-
// Do not Release() `devnull_read`, `pipe_write`, and `pipe_write_dup`. The
1192-
// subprocess inherits a copy of these handles and we need to close them in
1193-
// this process (via ~AutoHandle()).
1194-
startup_info.StartupInfo.hStdInput = devnull_read;
1195-
startup_info.StartupInfo.hStdOutput = pipe_write;
1196-
startup_info.StartupInfo.hStdError = pipe_write_dup;
1197-
startup_info.lpAttributeList = *attr_list.get();
1187+
attr_list->InitStartupInfoExW(&startup_info);
11981188

11991189
std::unique_ptr<WCHAR[]> cmdline;
12001190
if (!CreateCommandLine(path, args, &cmdline)) {

0 commit comments

Comments
 (0)