diff --git a/libc/intrin/msync-nt.c b/libc/intrin/msync-nt.c index 4d0494eb5..4e737678b 100644 --- a/libc/intrin/msync-nt.c +++ b/libc/intrin/msync-nt.c @@ -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? } diff --git a/libc/intrin/msync.c b/libc/intrin/msync.c index 3f9a58b5a..e9be44863 100644 --- a/libc/intrin/msync.c +++ b/libc/intrin/msync.c @@ -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()) { diff --git a/libc/log/gdb.h b/libc/log/gdb.h index 26e252a7c..b7d29fc0c 100644 --- a/libc/log/gdb.h +++ b/libc/log/gdb.h @@ -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_ diff --git a/libc/proc/fork-nt.c b/libc/proc/fork-nt.c index 4725c2466..20cef986c 100644 --- a/libc/proc/fork-nt.c +++ b/libc/proc/fork-nt.c @@ -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" diff --git a/libc/proc/fork.c b/libc/proc/fork.c index eb2213c94..046b7c983 100644 --- a/libc/proc/fork.c +++ b/libc/proc/fork.c @@ -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)) diff --git a/libc/proc/getpriority-nt.c b/libc/proc/getpriority-nt.c index 67d84363c..ff4fca305 100644 --- a/libc/proc/getpriority-nt.c +++ b/libc/proc/getpriority-nt.c @@ -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" diff --git a/libc/proc/getrusage-nt.c b/libc/proc/getrusage-nt.c index c13585337..07bde103a 100644 --- a/libc/proc/getrusage-nt.c +++ b/libc/proc/getrusage-nt.c @@ -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" diff --git a/libc/proc/handle.c b/libc/proc/handle.c index 10c220328..83c134e4a 100644 --- a/libc/proc/handle.c +++ b/libc/proc/handle.c @@ -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 diff --git a/libc/proc/kill-nt.c b/libc/proc/kill-nt.c index 6ce7abbf8..a820bf932 100644 --- a/libc/proc/kill-nt.c +++ b/libc/proc/kill-nt.c @@ -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__ diff --git a/libc/proc/posix_spawn.c b/libc/proc/posix_spawn.c index 3e653ff22..d2dcf7f41 100644 --- a/libc/proc/posix_spawn.c +++ b/libc/proc/posix_spawn.c @@ -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" diff --git a/libc/proc/proc.c b/libc/proc/proc.c index 972cc3a1b..0288075d1 100644 --- a/libc/proc/proc.c +++ b/libc/proc/proc.c @@ -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); } /** diff --git a/libc/proc/proc.internal.h b/libc/proc/proc.h similarity index 65% rename from libc/proc/proc.internal.h rename to libc/proc/proc.h index 6cf8d8bca..44b4ed5ad 100644 --- a/libc/proc/proc.internal.h +++ b/libc/proc/proc.h @@ -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_ */ diff --git a/libc/proc/sched_getaffinity.c b/libc/proc/sched_getaffinity.c index 5bddf33bf..752bc9c79 100644 --- a/libc/proc/sched_getaffinity.c +++ b/libc/proc/sched_getaffinity.c @@ -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" diff --git a/libc/proc/sched_setaffinity.c b/libc/proc/sched_setaffinity.c index 5e494ee98..79ab9fcfe 100644 --- a/libc/proc/sched_setaffinity.c +++ b/libc/proc/sched_setaffinity.c @@ -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( diff --git a/libc/proc/setpriority-nt.c b/libc/proc/setpriority-nt.c index 837bd8743..3aeb56dfc 100644 --- a/libc/proc/setpriority-nt.c +++ b/libc/proc/setpriority-nt.c @@ -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" diff --git a/libc/proc/wait4-nt.c b/libc/proc/wait4-nt.c index 9ea695ecf..8c17f09e0 100644 --- a/libc/proc/wait4-nt.c +++ b/libc/proc/wait4-nt.c @@ -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: diff --git a/libc/proc/wait4.c b/libc/proc/wait4.c index 056e9b371..0db1f4a81 100644 --- a/libc/proc/wait4.c +++ b/libc/proc/wait4.c @@ -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" /** diff --git a/test/libc/proc/fork_test.c b/test/libc/proc/fork_test.c index c3d6b0519..65b12baf8 100644 --- a/test/libc/proc/fork_test.c +++ b/test/libc/proc/fork_test.c @@ -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)); } diff --git a/test/libc/proc/posix_spawn_test.c b/test/libc/proc/posix_spawn_test.c index 2ddf868aa..809fc865d 100644 --- a/test/libc/proc/posix_spawn_test.c +++ b/test/libc/proc/posix_spawn_test.c @@ -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"