#define INFINITE 0xffffffffl
#define INVALID_HANDLE_VALUE ((void *)(intptr_t)(-1))
-
+#define STARTF_USESTDHANDLES 0x00000100
typedef DWORD WINAPI THREAD_START_ROUTINE(void *parameter);
char const * lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);
GB_DLL_IMPORT BOOL WINAPI GetExitCodeProcess (HANDLE hProcess, DWORD *lpExitCode);
+GB_DLL_IMPORT BOOL WINAPI CreatePipe (HANDLE *hReadPipe, HANDLE *hWritePipe, SECURITY_ATTRIBUTES* lpPipeAttributes,
+ DWORD nSize);
+GB_DLL_IMPORT BOOL WINAPI TerminateProcess (HANDLE hProcess, UINT uExitCode);
+GB_DLL_IMPORT BOOL WINAPI SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags);
GB_DLL_IMPORT BOOL WINAPI GetLogicalProcessorInformation(SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buffer, DWORD *return_length);
GB_DLL_IMPORT DWORD_PTR WINAPI SetThreadAffinityMask(HANDLE thread, DWORD_PTR check_mask);
use package core
#local wasi :: package wasi
+#local runtime :: package runtime
Directory_Entry :: struct {
dirent : wasi.DirEnt;
return .{ c, next, close };
}
-@Temporary
find_onyx_files :: (root: str, cases: ^[..] str) {
for list_directory(root) {
path_buffer: [512] u8;
main :: (args) => {
test_folder := "./tests";
+ onyx_cmd: str;
+ switch runtime.OS {
+ case runtime.OS_Linux do onyx_cmd = "./bin/onyx";
+ case runtime.OS_Windows do onyx_cmd = "onyx.exe";
+ }
+
cases := array.make(str);
find_onyx_files(test_folder, ^cases);
for cases {
printf("Running test {}...\n", it);
- proc := io.process_spawn("./bin/onyx", .["run", it]);
+ proc := io.process_spawn(onyx_cmd, .["run", it]);
defer io.process_destroy(^proc);
proc_reader := io.reader_make(^proc);
pid_t pid;
#endif
+
+#ifdef _BH_WINDOWS
+ HANDLE proc_to_host_read;
+ HANDLE proc_to_host_write;
+ HANDLE host_to_proc_read;
+ HANDLE host_to_proc_write;
+
+ PROCESS_INFORMATION proc_info;
+#endif
} OnyxProcess;
WASM_INTEROP(onyx_process_spawn_impl) {
process_args[0] = process_path;
process_args[args_len + 1] = NULL;
- pipe(process->proc_to_host);
- pipe(process->host_to_proc);
+ if (pipe(process->proc_to_host) || pipe(process->host_to_proc)) {
+ wasm_val_init_ptr(&results->data[0], NULL); // Failed to run
+ return NULL;
+ }
pid_t pid;
switch (pid = fork()) {
memset(&startup, 0, sizeof startup);
startup.cb = sizeof(startup);
- PROCESS_INFORMATION proc_info;
- BOOL success = CreateProcessA(process_path, cmdLine, NULL, NULL, 1, 0, NULL, NULL, &startup, &proc_info);
+ SECURITY_ATTRIBUTES saAttr;
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.lpSecurityDescriptor = NULL;
+ saAttr.bInheritHandle = 1;
+
+ BOOL success = 1;
+ success = success && CreatePipe(&process->host_to_proc_read, &process->host_to_proc_write, &saAttr, 4096);
+ success = success && CreatePipe(&process->proc_to_host_read, &process->proc_to_host_write, &saAttr, 4096);
if (!success) {
- results->data[0] = WASM_I32_VAL(1); // Failed to run
+ wasm_val_init_ptr(&results->data[0], NULL); // Failed to run @LEAK
return NULL;
}
- DWORD result = WaitForSingleObject(proc_info.hProcess, INFINITE);
- DWORD exitCode;
- GetExitCodeProcess(proc_info.hProcess, &exitCode);
- results->data[0] = WASM_I32_VAL(exitCode != 0 ? 2 : 0);
+ SetHandleInformation(process->proc_to_host_read, 1 /* HANDLE_FLAG_INHERIT */, 0);
+ SetHandleInformation(process->host_to_proc_write, 1 /* HANDLE_FLAG_INHERIT */, 0);
+
+ startup.hStdInput = process->host_to_proc_read;
+ startup.hStdOutput = process->proc_to_host_write;
+ startup.hStdError = process->proc_to_host_write;
+ startup.dwFlags |= STARTF_USESTDHANDLES;
+
+ success = CreateProcessA(process_path, cmdLine, NULL, NULL, 1, 0, NULL, NULL, &startup, &process->proc_info);
+ if (!success) {
+ wasm_val_init_ptr(&results->data[0], NULL); // Failed to run @LEAK
+ return NULL;
+ }
+
+ CloseHandle(process->proc_to_host_write);
+ CloseHandle(process->host_to_proc_read);
+ wasm_val_init_ptr(&results->data[0], process);
#endif
return NULL;
bytes_read = bh_max(bytes_read, 0); // Silently consume errors
#endif
+ #ifdef _BH_WINDOWS
+ BOOL success = ReadFile(process->proc_to_host_read, buffer, output_len, &bytes_read, NULL);
+ if (!success) bytes_read = 0;
+ #endif
+
results->data[0] = WASM_I32_VAL(bytes_read);
return NULL;
}
bytes_written = bh_max(bytes_written, 0); // Silently consume errors
#endif
+ #ifdef _BH_WINDOWS
+ BOOL success = WriteFile(process->host_to_proc_write, buffer, input_len, &bytes_written, NULL);
+ if (!success) bytes_written = 0;
+ #endif
+
results->data[0] = WASM_I32_VAL(bytes_written);
return NULL;
}
results->data[0] = WASM_I32_VAL(!failed);
#endif
+ #ifdef _BH_WINDOWS
+ BOOL success = TerminateProcess(process->proc_info.hProcess, 1);
+ results->data[0] = WASM_I32_VAL(success ? 1 : 0);
+ #endif
+
return NULL;
}
results->data[0] = WASM_I32_VAL(exit_code != 0 ? 2 : 0);
#endif
+ #ifdef _BH_WINDOWS
+ DWORD result = WaitForSingleObject(process->proc_info.hProcess, INFINITE);
+ CloseHandle(process->host_to_proc_write);
+ CloseHandle(process->proc_to_host_write);
+ CloseHandle(process->proc_to_host_read);
+
+ DWORD exitCode;
+ GetExitCodeProcess(process->proc_info.hProcess, &exitCode);
+ results->data[0] = WASM_I32_VAL(exitCode != 0 ? 2 : 0);
+ #endif
+
return NULL;
}
kill(process->pid, SIGKILL);
close(process->proc_to_host[0]);
close(process->host_to_proc[1]);
- bh_free(global_heap_allocator, process);
#endif
+ #ifdef _BH_WINDOWS
+ TerminateProcess(process->proc_info.hProcess, 1);
+ CloseHandle(process->host_to_proc_write);
+ CloseHandle(process->proc_to_host_write);
+ CloseHandle(process->proc_to_host_read);
+ #endif
+
+ bh_free(global_heap_allocator, process);
+
return NULL;
}