Fix fork() on Windows after chdir()

This commit is contained in:
Justine Tunney 2021-01-29 23:19:29 -08:00
parent 21e1023d28
commit b8d26e2418
7 changed files with 93 additions and 4 deletions

View file

@ -22,7 +22,9 @@
#include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h"
#include "libc/fmt/itoa.h"
#include "libc/macros.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nt/dll.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/enum/startf.h"
@ -119,6 +121,7 @@ textwindows void WinMainForked(void) {
textwindows int fork$nt(void) {
jmp_buf jb;
int i, rc, pid;
char exe[PATH_MAX];
int64_t reader, writer;
char *p, buf[21 + 1 + 21 + 1];
struct NtStartupInfo startinfo;
@ -137,8 +140,9 @@ textwindows int fork$nt(void) {
startinfo.hStdInput = g_fds.p[0].handle;
startinfo.hStdOutput = g_fds.p[1].handle;
startinfo.hStdError = g_fds.p[2].handle;
if (ntspawn(g_argv[0], g_argv, environ, &kNtIsInheritable, NULL, true, 0,
NULL, &startinfo, &procinfo) != -1) {
GetModuleFileNameA(0, exe, ARRAYLEN(exe));
if (ntspawn(exe, g_argv, environ, &kNtIsInheritable, NULL, true, 0, NULL,
&startinfo, &procinfo) != -1) {
CloseHandle(reader);
CloseHandle(procinfo.hThread);
if (weaken(__sighandrvas) &&

View file

@ -32,6 +32,7 @@ int64_t LoadLibraryEx(const char16_t *lpLibFileName, int64_t hFile,
uint32_t dwFlags);
uint32_t GetModuleFileName(int64_t hModule, char16_t *lpFilename,
uint32_t nSize);
uint32_t GetModuleFileNameA(int64_t hModule, char *lpFilename, uint32_t nSize);
intptr_t GetModuleHandle(const char *opt_lpModuleName);
intptr_t GetModuleHandleW(const char16_t *opt_lpModuleName);
void *GetProcAddress(int64_t hModule, const char *lpProcName);

View file

@ -199,6 +199,15 @@ bool32 WriteFileGather(int64_t hFileOpenedWithOverlappedAndNoBuffering,
uint32_t nNumberOfBytesToWrite, uint32_t *lpReserved,
struct NtOverlapped inout_lpOverlapped) paramsnonnull();
#define kNtFileNameNormalized 0x0
#define kNtVolumeNameDos 0x0
#define kNtVolumeNameGuid 0x1
#define kNtVolumeNameNt 0x2
#define kNtVolumeNameNone 0x4
#define kNtFileNameOpened 0x8
uint32_t GetFinalPathNameByHandle(int64_t hFile, char16_t *out_path,
uint32_t size, uint32_t flags);
#if ShouldUseMsabiAttribute()
#include "libc/nt/thunk/files.inc"
#endif /* ShouldUseMsabiAttribute() */

View file

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp kernel32,__imp_GetFinalPathNameByHandleA,GetFinalPathNameByHandleA,0
.text.windows
GetFinalPathNameByHandleA:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetFinalPathNameByHandleA(%rip),%rax
jmp __sysv2nt
.endfn GetFinalPathNameByHandleA,globl
.previous

View file

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp kernel32,__imp_GetFinalPathNameByHandleW,GetFinalPathNameByHandleW,0
.text.windows
GetFinalPathNameByHandle:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetFinalPathNameByHandleW(%rip),%rax
jmp __sysv2nt
.endfn GetFinalPathNameByHandle,globl
.previous

View file

@ -2176,8 +2176,8 @@ imp 'GetFileVersionInfoSizeExA' GetFileVersionInfoSizeExA KernelBase 561
imp 'GetFileVersionInfoSizeEx' GetFileVersionInfoSizeExW KernelBase 562
imp 'GetFileVersionInfoSize' GetFileVersionInfoSizeW KernelBase 563
imp 'GetFileVersionInfo' GetFileVersionInfoW KernelBase 564
imp 'GetFinalPathNameByHandleA' GetFinalPathNameByHandleA kernel32 0 # KernelBase
imp 'GetFinalPathNameByHandle' GetFinalPathNameByHandleW kernel32 0 # KernelBase
imp 'GetFinalPathNameByHandleA' GetFinalPathNameByHandleA kernel32 0 4 # KernelBase
imp 'GetFinalPathNameByHandle' GetFinalPathNameByHandleW kernel32 0 4 # KernelBase
imp 'GetFirmwareEnvironmentVariableA' GetFirmwareEnvironmentVariableA kernel32 597
imp 'GetFirmwareEnvironmentVariableExA' GetFirmwareEnvironmentVariableExA kernel32 598
imp 'GetFirmwareEnvironmentVariableEx' GetFirmwareEnvironmentVariableExW kernel32 599

View file

@ -0,0 +1,55 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/o.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
char testdir[PATH_MAX];
void SetUp(void) {
sprintf(testdir, "o/tmp/%s.%d", program_invocation_short_name, getpid());
makedirs(testdir, 0755);
CHECK_NE(-1, chdir(testdir));
}
void TearDown(void) {
CHECK_NE(-1, chdir("../../.."));
CHECK_NE(-1, rmrf(testdir));
}
TEST(lseek, wat) {
int fd, pid;
char buf[8] = {0};
ASSERT_NE(-1, (fd = open("wut", O_RDWR | O_CREAT, 0644)));
ASSERT_EQ(3, write(fd, "wut", 3));
ASSERT_NE(-1, lseek(fd, 0, SEEK_SET));
if (!(pid = fork())) {
lseek(fd, 1, SEEK_SET);
_exit(0);
}
EXPECT_NE(-1, waitpid(pid, 0, 0));
EXPECT_EQ(1, read(fd, buf, 1));
EXPECT_EQ('u', buf[0]); /* wat?! */
EXPECT_NE(-1, close(fd));
}