diff --git a/libc/calls/ntspawn.c b/libc/calls/ntspawn.c index cc16e05b0fc..cd75311481e 100644 --- a/libc/calls/ntspawn.c +++ b/libc/calls/ntspawn.c @@ -39,12 +39,15 @@ #include "libc/nt/struct/procthreadattributelist.h" #include "libc/nt/struct/startupinfo.h" #include "libc/nt/struct/startupinfoex.h" +#include "libc/nt/thunk/msabi.h" #include "libc/proc/ntspawn.h" #include "libc/stdalign.h" #include "libc/str/str.h" #include "libc/sysv/errfuns.h" #ifdef __x86_64__ +__msabi extern typeof(CloseHandle) *const __imp_CloseHandle; + struct SpawnBlock { char16_t path[PATH_MAX]; char16_t cmdline[32767]; @@ -64,10 +67,12 @@ static textwindows ssize_t ntspawn_read(intptr_t fh, char *buf, size_t len) { bool ok; uint32_t got; struct NtOverlapped overlap = {.hEvent = CreateEvent(0, 0, 0, 0)}; - ok = (ReadFile(fh, buf, len, 0, &overlap) || + ok = overlap.hEvent && + (ReadFile(fh, buf, len, 0, &overlap) || GetLastError() == kNtErrorIoPending) && GetOverlappedResult(fh, &overlap, &got, true); - CloseHandle(overlap.hEvent); + if (overlap.hEvent) + __imp_CloseHandle(overlap.hEvent); return ok ? got : -1; } @@ -87,7 +92,7 @@ static textwindows int ntspawn2(struct NtSpawnArgs *a, struct SpawnBlock *sb) { if (fh == -1) return -1; ssize_t got = ntspawn_read(fh, p, pe - p); - CloseHandle(fh); + __imp_CloseHandle(fh); if (got < 3) return enoexec(); pe = p + got; diff --git a/libc/proc/describefds.c b/libc/proc/describefds.c index 6cf25d78bca..847817595fe 100644 --- a/libc/proc/describefds.c +++ b/libc/proc/describefds.c @@ -68,6 +68,7 @@ textwindows void __undescribe_fds(int64_t hCreatorProcess, uint32_t dwExplicitHandleCount) { if (lpExplicitHandles) { for (uint32_t i = 0; i < dwExplicitHandleCount; ++i) { + STRACE("close handle %lx %lx", hCreatorProcess, lpExplicitHandles[i]); DuplicateHandle(hCreatorProcess, lpExplicitHandles[i], 0, 0, 0, false, kNtDuplicateCloseSource); } @@ -126,6 +127,7 @@ textwindows char *__describe_fds(const struct Fd *fds, size_t fdslen, for (uint32_t i = 0; i < 3; ++i) if (lpStartupInfo->stdiofds[i] == f->handle) lpStartupInfo->stdiofds[i] = handle; + STRACE("added handle %lx", handle); handles[hi++] = handle; // get shared memory handle for the file offset pointer @@ -142,6 +144,7 @@ textwindows char *__describe_fds(const struct Fd *fds, size_t fdslen, __winerr(); goto OnFailure; } + STRACE("added handle %lx", shand); handles[hi++] = shand; } diff --git a/libc/proc/execve-nt.greg.c b/libc/proc/execve-nt.greg.c index cfb0ab1fcd2..3b8aaa7660e 100644 --- a/libc/proc/execve-nt.greg.c +++ b/libc/proc/execve-nt.greg.c @@ -54,6 +54,7 @@ #include "libc/thread/thread.h" #ifdef __x86_64__ +__msabi extern typeof(CloseHandle) *const __imp_CloseHandle; __msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess; extern pthread_mutex_t __sig_worker_lock; @@ -69,8 +70,11 @@ textwindows int sys_execve_nt(const char *program, char *const argv[], // execve() needs to be @asyncsignalsafe sigset_t sigmask = __sig_block(); + STRACE("execve step #1"); _pthread_mutex_lock(&__sig_worker_lock); // order matters - _pthread_lock(); // order matters + STRACE("execve step #2"); + _pthread_lock(); // order matters + STRACE("execve step #3"); // new process should be a child of our parent int64_t hParentProcess = @@ -79,6 +83,8 @@ textwindows int sys_execve_nt(const char *program, char *const argv[], sys_getppid_nt_win32) : 0; + STRACE("execve step #4"); + // inherit pid char pidvar[11 + 21]; FormatUint64(stpcpy(pidvar, "_COSMO_PID="), __pid); @@ -97,6 +103,8 @@ textwindows int sys_execve_nt(const char *program, char *const argv[], setenv("_COSMO_PPID", ppidvar, true); } + STRACE("execve step #5"); + // define stdio handles for the spawned subprocess struct NtStartupInfo si = { .cb = sizeof(struct NtStartupInfo), @@ -110,6 +118,8 @@ textwindows int sys_execve_nt(const char *program, char *const argv[], } } + STRACE("execve step #6"); + // which process is responsible for spawning the child? int64_t hCreatorProcess; if (hParentProcess) { @@ -125,28 +135,34 @@ textwindows int sys_execve_nt(const char *program, char *const argv[], if (!(fdspec = __describe_fds(g_fds.p, g_fds.n, &si, hCreatorProcess, &lpExplicitHandles, &dwExplicitHandleCount))) { if (hParentProcess) - CloseHandle(hParentProcess); + __imp_CloseHandle(hParentProcess); sys_execve_nt_abort(sigmask); return -1; } + STRACE("execve step #7"); + // inherit pending signals atomic_fetch_or_explicit( __sig.process, atomic_load_explicit(&__get_tls()->tib_sigpending, memory_order_acquire), memory_order_release); + STRACE("execve step #8"); + // launch the process struct NtProcessInformation pi; int rc = ntspawn(&(struct NtSpawnArgs){ AT_FDCWD, program, argv, envp, (char *[]){fdspec, maskvar, pidvar, ppidvar, 0}, 0, 0, hCreatorProcess, lpExplicitHandles, dwExplicitHandleCount, &si, &pi}); + STRACE("execve step #9"); __undescribe_fds(hCreatorProcess, lpExplicitHandles, dwExplicitHandleCount); + STRACE("execve step #10"); if (rc == -1) { free(fdspec); if (hParentProcess) - CloseHandle(hParentProcess); + __imp_CloseHandle(hParentProcess); sys_execve_nt_abort(sigmask); if (GetLastError() == kNtErrorSharingViolation) { return etxtbsy(); @@ -161,9 +177,11 @@ textwindows int sys_execve_nt(const char *program, char *const argv[], int64_t handle; if (DuplicateHandle(GetCurrentProcess(), pi.hProcess, hParentProcess, &handle, 0, false, kNtDuplicateSameAccess)) { + STRACE("execve step #11"); unassert(!(handle & 0xFFFFFFFFFF000000)); __imp_TerminateProcess(-1, 0x23000000u | handle); } else { + STRACE("execve step #12"); // TODO(jart): Why does `make loc` print this? // kprintf("DuplicateHandle failed w/ %d\n", GetLastError()); __imp_TerminateProcess(-1, ECHILD); @@ -194,7 +212,7 @@ textwindows int sys_execve_nt(const char *program, char *const argv[], if (status != kNtStillActive) { if ((status & 0xFF000000u) == 0x23000000u) { // handle child execve() - CloseHandle(pi.hProcess); + __imp_CloseHandle(pi.hProcess); pi.hProcess = status & 0x00FFFFFF; } else { // handle child _Exit()