24
24
#include < stdlib.h>
25
25
#include < vector>
26
26
27
+ #ifdef _WIN32
28
+ #include < system_error>
29
+ #include < windows.h>
30
+ #endif
31
+
27
32
using namespace sycl ;
28
33
using namespace std ::literals;
29
34
@@ -196,6 +201,63 @@ static void unsetFilterEnvVars() {
196
201
}
197
202
}
198
203
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
+
199
261
int main (int argc, char **argv) {
200
262
201
263
if (argc == 1 ) {
@@ -218,9 +280,18 @@ int main(int argc, char **argv) {
218
280
// the filter environment variable is set.
219
281
printWarningIfFiltersUsed (SuppressNumberPrinting);
220
282
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
+
221
292
try {
222
293
// Unset all filter env. vars to get all available devices in the system.
223
- if (DiscardFilters)
294
+ if (DiscardFilters && FilterEnvVars. size () )
224
295
unsetFilterEnvVars ();
225
296
226
297
const auto &Platforms = platform::get_platforms ();
0 commit comments