mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Add missing lock to fork() on Windows
This commit is contained in:
parent
e939659b70
commit
fe01642a20
19 changed files with 90 additions and 96 deletions
|
@ -19,10 +19,8 @@
|
|||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/intrin/maps.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -36,28 +34,17 @@ textwindows int sys_msync_nt(char *addr, size_t size, int flags) {
|
|||
|
||||
int rc = 0;
|
||||
__maps_lock();
|
||||
struct Map *next, *map;
|
||||
struct Map *map;
|
||||
if (!(map = __maps_floor(addr)))
|
||||
map = __maps_first();
|
||||
for (; map && map->addr <= addr + size; map = next) {
|
||||
next = __maps_next(map);
|
||||
if (!__maps_isalloc(map))
|
||||
continue;
|
||||
for (; map && map->addr <= addr + size; map = __maps_next(map)) {
|
||||
if (map->flags & MAP_ANONYMOUS)
|
||||
continue;
|
||||
if (MAX(addr, map->addr) >= MIN(addr + size, map->addr + map->size))
|
||||
continue; // msync() is about coherency between file and memory
|
||||
char *beg = MAX(addr, map->addr);
|
||||
char *end = MIN(addr + size, map->addr + map->size);
|
||||
if (beg >= end)
|
||||
continue; // didn't overlap mapping
|
||||
|
||||
// get true size of win32 allocation
|
||||
size_t allocsize = map->size;
|
||||
while (next && !__maps_isalloc(next) &&
|
||||
next->addr + allocsize == next->addr) {
|
||||
allocsize += next->size;
|
||||
next = __maps_next(next);
|
||||
}
|
||||
|
||||
// perform the flush
|
||||
if (!FlushViewOfFile(map->addr, allocsize))
|
||||
if (!FlushViewOfFile(beg, end - beg))
|
||||
rc = -1;
|
||||
// TODO(jart): FlushFileBuffers too on g_fds handle if MS_SYNC?
|
||||
}
|
||||
|
|
|
@ -68,23 +68,19 @@ int msync(void *addr, size_t size, int flags) {
|
|||
} else {
|
||||
sysflags = MS_ASYNC;
|
||||
}
|
||||
if (flags & MS_INVALIDATE) {
|
||||
if (flags & MS_INVALIDATE)
|
||||
sysflags |= MS_INVALIDATE;
|
||||
}
|
||||
|
||||
// FreeBSD's manual says "The flags argument was both MS_ASYNC and
|
||||
// MS_INVALIDATE. Only one of these flags is allowed." which makes
|
||||
// following the POSIX recommendation somewhat difficult.
|
||||
if (IsFreebsd()) {
|
||||
if (sysflags == (MS_ASYNC | MS_INVALIDATE)) {
|
||||
if (IsFreebsd())
|
||||
if (sysflags == (MS_ASYNC | MS_INVALIDATE))
|
||||
sysflags = MS_INVALIDATE;
|
||||
}
|
||||
}
|
||||
|
||||
// FreeBSD specifies MS_SYNC as 0 so we shift the Cosmo constants
|
||||
if (IsFreebsd()) {
|
||||
if (IsFreebsd())
|
||||
sysflags >>= 1;
|
||||
}
|
||||
|
||||
BEGIN_CANCELATION_POINT;
|
||||
if (!IsWindows()) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#include "libc/nt/thread.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
|
@ -119,6 +119,9 @@ static void fork_prepare(void) {
|
|||
_weaken(__localtime_lock)();
|
||||
if (_weaken(__dlopen_lock))
|
||||
_weaken(__dlopen_lock)();
|
||||
if (IsWindows())
|
||||
if (_weaken(__proc_lock))
|
||||
_weaken(__proc_lock)();
|
||||
if (_weaken(cosmo_stack_lock))
|
||||
_weaken(cosmo_stack_lock)();
|
||||
__cxa_lock();
|
||||
|
@ -151,6 +154,9 @@ static void fork_parent(void) {
|
|||
__cxa_unlock();
|
||||
if (_weaken(cosmo_stack_unlock))
|
||||
_weaken(cosmo_stack_unlock)();
|
||||
if (IsWindows())
|
||||
if (_weaken(__proc_unlock))
|
||||
_weaken(__proc_unlock)();
|
||||
if (_weaken(__dlopen_unlock))
|
||||
_weaken(__dlopen_unlock)();
|
||||
if (_weaken(__localtime_unlock))
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/sysv/consts/prio.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "libc/nt/struct/iocounters.h"
|
||||
#include "libc/nt/struct/processmemorycounters.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/rusage.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
|
||||
// retrieves handle of process
|
||||
// supports only current process and processes we created
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#ifdef __x86_64__
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
#include "libc/proc/ntspawn.h"
|
||||
#include "libc/proc/posix_spawn.h"
|
||||
#include "libc/proc/posix_spawn.internal.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
|
@ -47,7 +48,6 @@
|
|||
#include "libc/nt/struct/processmemorycounters.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
|
@ -67,9 +67,8 @@
|
|||
|
||||
#define STACK_SIZE 65536
|
||||
|
||||
struct Procs __proc = {
|
||||
.lock = PTHREAD_MUTEX_INITIALIZER,
|
||||
};
|
||||
struct Procs __proc;
|
||||
static pthread_mutex_t __proc_lock_obj = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
textwindows static void __proc_stats(int64_t h, struct rusage *ru) {
|
||||
bzero(ru, sizeof(*ru));
|
||||
|
@ -258,14 +257,14 @@ textwindows static void __proc_setup(void) {
|
|||
*/
|
||||
textwindows void __proc_lock(void) {
|
||||
cosmo_once(&__proc.once, __proc_setup);
|
||||
_pthread_mutex_lock(&__proc.lock);
|
||||
_pthread_mutex_lock(&__proc_lock_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks process tracker.
|
||||
*/
|
||||
textwindows void __proc_unlock(void) {
|
||||
_pthread_mutex_unlock(&__proc.lock);
|
||||
_pthread_mutex_unlock(&__proc_lock_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -273,10 +272,8 @@ textwindows void __proc_unlock(void) {
|
|||
*/
|
||||
textwindows void __proc_wipe_and_reset(void) {
|
||||
// TODO(jart): Should we preserve this state in forked children?
|
||||
pthread_mutex_t lock = __proc.lock;
|
||||
_pthread_mutex_wipe_np(&__proc_lock_obj);
|
||||
bzero(&__proc, sizeof(__proc));
|
||||
__proc.lock = lock;
|
||||
_pthread_mutex_wipe_np(&__proc.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,6 @@ struct Proc {
|
|||
struct Procs {
|
||||
int waiters;
|
||||
atomic_uint once;
|
||||
pthread_mutex_t lock;
|
||||
intptr_t thread;
|
||||
intptr_t onbirth;
|
||||
intptr_t haszombies;
|
||||
|
@ -41,16 +40,16 @@ struct Procs {
|
|||
|
||||
extern struct Procs __proc;
|
||||
|
||||
void __proc_lock(void) dontthrow;
|
||||
void __proc_unlock(void) dontthrow;
|
||||
int64_t __proc_handle(int) libcesque;
|
||||
int64_t __proc_search(int) libcesque;
|
||||
struct Proc *__proc_new(void) libcesque;
|
||||
void __proc_add(struct Proc *) libcesque;
|
||||
void __proc_free(struct Proc *) libcesque;
|
||||
void __proc_wipe_and_reset(void) libcesque;
|
||||
int __proc_harvest(struct Proc *, bool) libcesque;
|
||||
int sys_wait4_nt(int, int *, int, struct rusage *) libcesque;
|
||||
void __proc_lock(void);
|
||||
void __proc_unlock(void);
|
||||
int64_t __proc_handle(int);
|
||||
int64_t __proc_search(int);
|
||||
struct Proc *__proc_new(void);
|
||||
void __proc_add(struct Proc *);
|
||||
void __proc_free(struct Proc *);
|
||||
void __proc_wipe_and_reset(void);
|
||||
int __proc_harvest(struct Proc *, bool);
|
||||
int sys_wait4_nt(int, int *, int, struct rusage *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_PROC_H_ */
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static dontinline textwindows int sys_sched_setaffinity_nt(
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/sysv/consts/prio.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
|
@ -27,25 +28,22 @@
|
|||
#include "libc/nt/events.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#ifdef __x86_64__
|
||||
|
||||
static textwindows int __proc_reap(struct Proc *pr, int *wstatus,
|
||||
textwindows static int __proc_reap(struct Proc *pr, int *wstatus,
|
||||
struct rusage *opt_out_rusage) {
|
||||
if (wstatus) {
|
||||
if (wstatus)
|
||||
*wstatus = pr->wstatus;
|
||||
}
|
||||
if (opt_out_rusage) {
|
||||
if (opt_out_rusage)
|
||||
*opt_out_rusage = pr->ru;
|
||||
}
|
||||
dll_remove(&__proc.zombies, &pr->elem);
|
||||
if (dll_is_empty(__proc.zombies)) {
|
||||
if (dll_is_empty(__proc.zombies))
|
||||
ResetEvent(__proc.haszombies);
|
||||
}
|
||||
if (pr->waiters) {
|
||||
pr->status = PROC_UNDEAD;
|
||||
dll_make_first(&__proc.undead, &pr->elem);
|
||||
|
@ -56,19 +54,18 @@ static textwindows int __proc_reap(struct Proc *pr, int *wstatus,
|
|||
return pr->pid;
|
||||
}
|
||||
|
||||
static textwindows int __proc_check(int pid, int *wstatus,
|
||||
textwindows static int __proc_check(int pid, int *wstatus,
|
||||
struct rusage *opt_out_rusage) {
|
||||
struct Dll *e;
|
||||
for (e = dll_first(__proc.zombies); e; e = dll_next(__proc.zombies, e)) {
|
||||
struct Proc *pr = PROC_CONTAINER(e);
|
||||
if (pid == -1 || pid == pr->pid) {
|
||||
if (pid == -1 || pid == pr->pid)
|
||||
return __proc_reap(pr, wstatus, opt_out_rusage);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static textwindows int __proc_wait(int pid, int *wstatus, int options,
|
||||
textwindows static int __proc_wait(int pid, int *wstatus, int options,
|
||||
struct rusage *rusage, sigset_t waitmask) {
|
||||
for (;;) {
|
||||
|
||||
|
@ -159,9 +156,8 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
|
|||
// check if killed or win32 error
|
||||
if (wi) {
|
||||
if (pr) {
|
||||
if (!--pr->waiters && pr->status == PROC_UNDEAD) {
|
||||
if (!--pr->waiters && pr->status == PROC_UNDEAD)
|
||||
__proc_free(pr);
|
||||
}
|
||||
} else {
|
||||
--__proc.waiters;
|
||||
}
|
||||
|
@ -178,17 +174,15 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
|
|||
|
||||
// handle process exit notification
|
||||
--pr->waiters;
|
||||
if (pr->status == PROC_ALIVE) {
|
||||
if (pr->status == PROC_ALIVE)
|
||||
__proc_harvest(pr, true);
|
||||
}
|
||||
switch (pr->status) {
|
||||
case PROC_ALIVE:
|
||||
// exit caused by execve() reparenting
|
||||
__proc_unlock();
|
||||
if (!pr->waiters) {
|
||||
if (!pr->waiters)
|
||||
// avoid deadlock that could theoretically happen
|
||||
SetEvent(__proc.onbirth);
|
||||
}
|
||||
__proc_unlock();
|
||||
break;
|
||||
case PROC_ZOMBIE:
|
||||
// exit happened and we're the first to know
|
||||
|
@ -197,9 +191,8 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
|
|||
return rc;
|
||||
case PROC_UNDEAD:
|
||||
// exit happened but another thread waited first
|
||||
if (!pr->waiters) {
|
||||
if (!pr->waiters)
|
||||
__proc_free(pr);
|
||||
}
|
||||
__proc_unlock();
|
||||
return echild();
|
||||
default:
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/calls/struct/rusage.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,11 +24,13 @@
|
|||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/proc/posix_spawn.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
|
@ -38,6 +40,7 @@
|
|||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
void SetUpOnce(void) {
|
||||
|
@ -70,32 +73,27 @@ TEST(fork, testSharedMemory) {
|
|||
int *sharedvar;
|
||||
int *privatevar;
|
||||
EXPECT_NE(MAP_FAILED,
|
||||
(sharedvar = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
|
||||
(sharedvar = mmap(0, getpagesize(), PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS, -1, 0)));
|
||||
EXPECT_NE(MAP_FAILED,
|
||||
(privatevar = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
|
||||
(privatevar = mmap(0, getpagesize(), PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
|
||||
stackvar = 1;
|
||||
*sharedvar = 1;
|
||||
*privatevar = 1;
|
||||
EXPECT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
EXPECT_EQ(NULL, getenv("_FORK"));
|
||||
++stackvar;
|
||||
++*sharedvar;
|
||||
++*privatevar;
|
||||
msync((void *)ROUNDDOWN((intptr_t)&stackvar, getpagesize()), getpagesize(),
|
||||
MS_SYNC);
|
||||
EXPECT_NE(-1, msync(privatevar, getpagesize(), MS_SYNC));
|
||||
EXPECT_NE(-1, msync(sharedvar, getpagesize(), MS_SYNC));
|
||||
++*sharedvar;
|
||||
_exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, waitpid(pid, &ws, 0));
|
||||
EXPECT_EQ(1, stackvar);
|
||||
EXPECT_EQ(2, *sharedvar);
|
||||
EXPECT_EQ(1, *privatevar);
|
||||
EXPECT_NE(-1, munmap(sharedvar, getpagesize()));
|
||||
EXPECT_NE(-1, munmap(privatevar, getpagesize()));
|
||||
EXPECT_SYS(0, 0, munmap(sharedvar, getpagesize()));
|
||||
EXPECT_SYS(0, 0, munmap(privatevar, getpagesize()));
|
||||
}
|
||||
|
||||
static volatile bool gotsigusr1;
|
||||
|
@ -123,14 +121,20 @@ TEST(fork, childToChild) {
|
|||
sigprocmask(SIG_BLOCK, &mask, &oldmask);
|
||||
ASSERT_NE(-1, (child1 = fork()));
|
||||
if (!child1) {
|
||||
kill(parent, SIGUSR2);
|
||||
sigsuspend(0);
|
||||
if (kill(parent, SIGUSR2)) {
|
||||
kprintf("%s:%d: error: failed to kill parent: %m\n", __FILE__, __LINE__);
|
||||
_Exit(1);
|
||||
}
|
||||
ASSERT_SYS(EINTR, -1, sigsuspend(0));
|
||||
_Exit(!gotsigusr1);
|
||||
}
|
||||
sigsuspend(0);
|
||||
EXPECT_SYS(EINTR, -1, sigsuspend(0));
|
||||
ASSERT_NE(-1, (child2 = fork()));
|
||||
if (!child2) {
|
||||
kill(child1, SIGUSR1);
|
||||
if (kill(child1, SIGUSR1)) {
|
||||
kprintf("%s:%d: error: failed to kill child1: %m\n", __FILE__, __LINE__);
|
||||
_Exit(1);
|
||||
}
|
||||
_Exit(0);
|
||||
}
|
||||
ASSERT_NE(-1, wait(&ws));
|
||||
|
@ -147,12 +151,20 @@ TEST(fork, preservesTlsMemory) {
|
|||
EXITS(0);
|
||||
}
|
||||
|
||||
#define CHECK_TERMSIG \
|
||||
if (WIFSIGNALED(ws)) { \
|
||||
kprintf("%s:%d: error: forked life subprocess terminated with %G\n", \
|
||||
__FILE__, __LINE__, WTERMSIG(ws)); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
void fork_wait_in_serial(void) {
|
||||
int pid, ws;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid)
|
||||
_Exit(0);
|
||||
ASSERT_NE(-1, waitpid(pid, &ws, 0));
|
||||
CHECK_TERMSIG;
|
||||
ASSERT_TRUE(WIFEXITED(ws));
|
||||
ASSERT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
@ -165,6 +177,7 @@ void vfork_execl_wait_in_serial(void) {
|
|||
_Exit(127);
|
||||
}
|
||||
ASSERT_NE(-1, waitpid(pid, &ws, 0));
|
||||
CHECK_TERMSIG;
|
||||
ASSERT_TRUE(WIFEXITED(ws));
|
||||
ASSERT_EQ(42, WEXITSTATUS(ws));
|
||||
}
|
||||
|
@ -175,6 +188,7 @@ void vfork_wait_in_serial(void) {
|
|||
if (!pid)
|
||||
_Exit(0);
|
||||
ASSERT_NE(-1, waitpid(pid, &ws, 0));
|
||||
CHECK_TERMSIG;
|
||||
ASSERT_TRUE(WIFEXITED(ws));
|
||||
ASSERT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
@ -185,6 +199,7 @@ void sys_fork_wait_in_serial(void) {
|
|||
if (!pid)
|
||||
_Exit(0);
|
||||
ASSERT_NE(-1, waitpid(pid, &ws, 0));
|
||||
CHECK_TERMSIG;
|
||||
ASSERT_TRUE(WIFEXITED(ws));
|
||||
ASSERT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
@ -196,6 +211,7 @@ void posix_spawn_in_serial(void) {
|
|||
char *envs[] = {NULL};
|
||||
ASSERT_EQ(0, posix_spawn(&pid, prog, NULL, NULL, args, envs));
|
||||
ASSERT_NE(-1, waitpid(pid, &ws, 0));
|
||||
CHECK_TERMSIG;
|
||||
ASSERT_TRUE(WIFEXITED(ws));
|
||||
ASSERT_EQ(42, WEXITSTATUS(ws));
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
#include "libc/proc/proc.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
Loading…
Add table
Reference in a new issue