Skip to content

Commit 6e9a3dd

Browse files
[SYCL] Fix 'ignore-device-selectors' sycl-ls CLI option on windows (#13047)
Fixes LIT test failure in tools/sycl-ls.test.
1 parent 9431225 commit 6e9a3dd

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

sycl/tools/sycl-ls/sycl-ls.cpp

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
#include <stdlib.h>
2525
#include <vector>
2626

27+
#ifdef _WIN32
28+
#include <system_error>
29+
#include <windows.h>
30+
#endif
31+
2732
using namespace sycl;
2833
using namespace std::literals;
2934

@@ -196,6 +201,63 @@ static void unsetFilterEnvVars() {
196201
}
197202
}
198203

204+
/* On Windows, the sycl-ls executable and sycl DLL have different copies
205+
* of environment variables. So, just unsetting device filter env. vars
206+
* in sycl-ls won't reflect in sycl DLL. Therefore, on Windows, after
207+
* unsetting env. variables in the parent process, we spawn a child
208+
* sycl-ls process that inherits parents envirnonment.
209+
*/
210+
#ifdef _WIN32
211+
static int unsetFilterEnvVarsAndFork() {
212+
// Unset all device filter enviornment variable.
213+
unsetFilterEnvVars();
214+
215+
// Create a new sycl-ls process.
216+
STARTUPINFO si;
217+
memset(&si, 0, sizeof(si));
218+
si.cb = sizeof(si);
219+
// Redirect child process's stdout and stderr outputs to parent process.
220+
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
221+
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
222+
si.dwFlags |= STARTF_USESTDHANDLES;
223+
224+
PROCESS_INFORMATION pi;
225+
if (!CreateProcess(NULL, /* Applicatioon name. */
226+
GetCommandLine(), /* Current process's CLI input. */
227+
NULL, /* Inherit security attributes. */
228+
NULL, /* Thread security attributes. */
229+
TRUE, /* Inherit handles from parent proc.*/
230+
0, /* Creation flags. */
231+
NULL, /* Inherit env. block from parent.*/
232+
NULL, /* Inherit current directory. */
233+
&si, &pi)) {
234+
// Unable to create a process. Print error message and abort.
235+
std::string message = std::system_category().message(GetLastError());
236+
std::cerr << message.c_str() << std::endl;
237+
238+
std::cerr << "Error creating a new sycl-ls process. Aborting!" << std::endl;
239+
return EXIT_FAILURE;
240+
}
241+
242+
// Wait for child process to finish.
243+
WaitForSingleObject(pi.hProcess, INFINITE);
244+
245+
// Check child process's exit code and propagate it.
246+
DWORD exitCode;
247+
if (!GetExitCodeProcess(pi.hProcess, &exitCode)) {
248+
std::cerr << "Error getting exit code. Aborting!" << std::endl;
249+
return EXIT_FAILURE;
250+
}
251+
252+
assert(exitCode != STILL_ACTIVE &&
253+
"The child process should have already terminated");
254+
255+
CloseHandle(pi.hProcess);
256+
CloseHandle(pi.hThread);
257+
return exitCode;
258+
}
259+
#endif
260+
199261
int main(int argc, char **argv) {
200262

201263
if (argc == 1) {
@@ -218,9 +280,18 @@ int main(int argc, char **argv) {
218280
// the filter environment variable is set.
219281
printWarningIfFiltersUsed(SuppressNumberPrinting);
220282

283+
// On Windows, to print all devices available on the system,
284+
// we spawn a child sycl-ls process with all device filter
285+
// environment variables unset.
286+
#ifdef _WIN32
287+
if (DiscardFilters && FilterEnvVars.size()) {
288+
return unsetFilterEnvVarsAndFork();
289+
}
290+
#endif
291+
221292
try {
222293
// Unset all filter env. vars to get all available devices in the system.
223-
if (DiscardFilters)
294+
if (DiscardFilters && FilterEnvVars.size())
224295
unsetFilterEnvVars();
225296

226297
const auto &Platforms = platform::get_platforms();

0 commit comments

Comments
 (0)