Skip to content

Commit b8d26e2

Browse files
committed
Fix fork() on Windows after chdir()
1 parent 21e1023 commit b8d26e2

File tree

7 files changed

+93
-4
lines changed

7 files changed

+93
-4
lines changed

libc/calls/hefty/fork-nt.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
#include "libc/calls/internal.h"
2323
#include "libc/calls/ntspawn.h"
2424
#include "libc/fmt/itoa.h"
25+
#include "libc/macros.h"
2526
#include "libc/nexgen32e/nt2sysv.h"
27+
#include "libc/nt/dll.h"
2628
#include "libc/nt/enum/filemapflags.h"
2729
#include "libc/nt/enum/pageflags.h"
2830
#include "libc/nt/enum/startf.h"
@@ -119,6 +121,7 @@ textwindows void WinMainForked(void) {
119121
textwindows int fork$nt(void) {
120122
jmp_buf jb;
121123
int i, rc, pid;
124+
char exe[PATH_MAX];
122125
int64_t reader, writer;
123126
char *p, buf[21 + 1 + 21 + 1];
124127
struct NtStartupInfo startinfo;
@@ -137,8 +140,9 @@ textwindows int fork$nt(void) {
137140
startinfo.hStdInput = g_fds.p[0].handle;
138141
startinfo.hStdOutput = g_fds.p[1].handle;
139142
startinfo.hStdError = g_fds.p[2].handle;
140-
if (ntspawn(g_argv[0], g_argv, environ, &kNtIsInheritable, NULL, true, 0,
141-
NULL, &startinfo, &procinfo) != -1) {
143+
GetModuleFileNameA(0, exe, ARRAYLEN(exe));
144+
if (ntspawn(exe, g_argv, environ, &kNtIsInheritable, NULL, true, 0, NULL,
145+
&startinfo, &procinfo) != -1) {
142146
CloseHandle(reader);
143147
CloseHandle(procinfo.hThread);
144148
if (weaken(__sighandrvas) &&

libc/nt/dll.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ int64_t LoadLibraryEx(const char16_t *lpLibFileName, int64_t hFile,
3232
uint32_t dwFlags);
3333
uint32_t GetModuleFileName(int64_t hModule, char16_t *lpFilename,
3434
uint32_t nSize);
35+
uint32_t GetModuleFileNameA(int64_t hModule, char *lpFilename, uint32_t nSize);
3536
intptr_t GetModuleHandle(const char *opt_lpModuleName);
3637
intptr_t GetModuleHandleW(const char16_t *opt_lpModuleName);
3738
void *GetProcAddress(int64_t hModule, const char *lpProcName);

libc/nt/files.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,15 @@ bool32 WriteFileGather(int64_t hFileOpenedWithOverlappedAndNoBuffering,
199199
uint32_t nNumberOfBytesToWrite, uint32_t *lpReserved,
200200
struct NtOverlapped inout_lpOverlapped) paramsnonnull();
201201

202+
#define kNtFileNameNormalized 0x0
203+
#define kNtVolumeNameDos 0x0
204+
#define kNtVolumeNameGuid 0x1
205+
#define kNtVolumeNameNt 0x2
206+
#define kNtVolumeNameNone 0x4
207+
#define kNtFileNameOpened 0x8
208+
uint32_t GetFinalPathNameByHandle(int64_t hFile, char16_t *out_path,
209+
uint32_t size, uint32_t flags);
210+
202211
#if ShouldUseMsabiAttribute()
203212
#include "libc/nt/thunk/files.inc"
204213
#endif /* ShouldUseMsabiAttribute() */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
11
.include "o/libc/nt/codegen.inc"
22
.imp kernel32,__imp_GetFinalPathNameByHandleA,GetFinalPathNameByHandleA,0
3+
4+
.text.windows
5+
GetFinalPathNameByHandleA:
6+
push %rbp
7+
mov %rsp,%rbp
8+
.profilable
9+
mov __imp_GetFinalPathNameByHandleA(%rip),%rax
10+
jmp __sysv2nt
11+
.endfn GetFinalPathNameByHandleA,globl
12+
.previous
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
11
.include "o/libc/nt/codegen.inc"
22
.imp kernel32,__imp_GetFinalPathNameByHandleW,GetFinalPathNameByHandleW,0
3+
4+
.text.windows
5+
GetFinalPathNameByHandle:
6+
push %rbp
7+
mov %rsp,%rbp
8+
.profilable
9+
mov __imp_GetFinalPathNameByHandleW(%rip),%rax
10+
jmp __sysv2nt
11+
.endfn GetFinalPathNameByHandle,globl
12+
.previous

libc/nt/master.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,8 +2176,8 @@ imp 'GetFileVersionInfoSizeExA' GetFileVersionInfoSizeExA KernelBase 561
21762176
imp 'GetFileVersionInfoSizeEx' GetFileVersionInfoSizeExW KernelBase 562
21772177
imp 'GetFileVersionInfoSize' GetFileVersionInfoSizeW KernelBase 563
21782178
imp 'GetFileVersionInfo' GetFileVersionInfoW KernelBase 564
2179-
imp 'GetFinalPathNameByHandleA' GetFinalPathNameByHandleA kernel32 0 # KernelBase
2180-
imp 'GetFinalPathNameByHandle' GetFinalPathNameByHandleW kernel32 0 # KernelBase
2179+
imp 'GetFinalPathNameByHandleA' GetFinalPathNameByHandleA kernel32 0 4 # KernelBase
2180+
imp 'GetFinalPathNameByHandle' GetFinalPathNameByHandleW kernel32 0 4 # KernelBase
21812181
imp 'GetFirmwareEnvironmentVariableA' GetFirmwareEnvironmentVariableA kernel32 597
21822182
imp 'GetFirmwareEnvironmentVariableExA' GetFirmwareEnvironmentVariableExA kernel32 598
21832183
imp 'GetFirmwareEnvironmentVariableEx' GetFirmwareEnvironmentVariableExW kernel32 599

test/libc/calls/lseek_test.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
2+
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
3+
╞══════════════════════════════════════════════════════════════════════════════╡
4+
│ Copyright 2021 Justine Alexandra Roberts Tunney │
5+
│ │
6+
│ Permission to use, copy, modify, and/or distribute this software for │
7+
│ any purpose with or without fee is hereby granted, provided that the │
8+
│ above copyright notice and this permission notice appear in all copies. │
9+
│ │
10+
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
11+
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
12+
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
13+
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
14+
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
15+
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
16+
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17+
│ PERFORMANCE OF THIS SOFTWARE. │
18+
╚─────────────────────────────────────────────────────────────────────────────*/
19+
#include "libc/calls/calls.h"
20+
#include "libc/calls/internal.h"
21+
#include "libc/fmt/fmt.h"
22+
#include "libc/log/check.h"
23+
#include "libc/runtime/runtime.h"
24+
#include "libc/sysv/consts/o.h"
25+
#include "libc/testlib/testlib.h"
26+
#include "libc/x/x.h"
27+
28+
char testdir[PATH_MAX];
29+
30+
void SetUp(void) {
31+
sprintf(testdir, "o/tmp/%s.%d", program_invocation_short_name, getpid());
32+
makedirs(testdir, 0755);
33+
CHECK_NE(-1, chdir(testdir));
34+
}
35+
36+
void TearDown(void) {
37+
CHECK_NE(-1, chdir("../../.."));
38+
CHECK_NE(-1, rmrf(testdir));
39+
}
40+
41+
TEST(lseek, wat) {
42+
int fd, pid;
43+
char buf[8] = {0};
44+
ASSERT_NE(-1, (fd = open("wut", O_RDWR | O_CREAT, 0644)));
45+
ASSERT_EQ(3, write(fd, "wut", 3));
46+
ASSERT_NE(-1, lseek(fd, 0, SEEK_SET));
47+
if (!(pid = fork())) {
48+
lseek(fd, 1, SEEK_SET);
49+
_exit(0);
50+
}
51+
EXPECT_NE(-1, waitpid(pid, 0, 0));
52+
EXPECT_EQ(1, read(fd, buf, 1));
53+
EXPECT_EQ('u', buf[0]); /* wat?! */
54+
EXPECT_NE(-1, close(fd));
55+
}

0 commit comments

Comments
 (0)