Improve performance and remove fd leaks

This commit is contained in:
Justine Tunney 2023-09-10 11:52:03 -07:00
parent 26e254fb4d
commit 1965d7488e
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
17 changed files with 131 additions and 159 deletions

View file

@ -69,6 +69,8 @@ $(LIBC_CALLS_A).pkg: \
# we're on a stack owned by win32 without tls # we're on a stack owned by win32 without tls
o/$(MODE)/libc/calls/foist.o \ o/$(MODE)/libc/calls/foist.o \
o/$(MODE)/libc/calls/__sig2.o \ o/$(MODE)/libc/calls/__sig2.o \
o/$(MODE)/libc/calls/sigchld-nt.o \
o/$(MODE)/libc/calls/sigwinch-nt.o \
o/$(MODE)/libc/calls/onntconsoleevent.o \ o/$(MODE)/libc/calls/onntconsoleevent.o \
o/$(MODE)/libc/calls/wincrash.o \ o/$(MODE)/libc/calls/wincrash.o \
o/$(MODE)/libc/calls/ntcontext2linux.o: private \ o/$(MODE)/libc/calls/ntcontext2linux.o: private \

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h" #include "libc/calls/ntspawn.h"
#include "libc/calls/struct/sigaction.internal.h"
#include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall-nt.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
@ -166,6 +167,8 @@ keywords int sys_execve_nt(const char *program, char *const argv[],
// kill siblings // kill siblings
sys_execve_killer(); sys_execve_killer();
PurgeThread(*_weaken(__sigchld_thread));
PurgeThread(*_weaken(__sigwinch_thread));
// close win32 handles for memory mappings // close win32 handles for memory mappings
// unlike fork calling execve destroys all memory // unlike fork calling execve destroys all memory

View file

@ -16,19 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h" #include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigaction.internal.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h" #include "libc/intrin/weaken.h"
#include "libc/nt/struct/windowplacement.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h" #include "libc/thread/thread.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
@ -51,14 +44,6 @@ textwindows int _check_interrupts(int sigops) {
if (__tls_enabled) { if (__tls_enabled) {
__get_tls()->tib_flags = flags; __get_tls()->tib_flags = flags;
} }
if (_weaken(_check_sigwinch)) {
_weaken(_check_sigwinch)();
}
if (!__tls_enabled || !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
if (!(sigops & kSigOpNochld) && _weaken(_check_sigchld)) {
_weaken(_check_sigchld)();
}
}
if (_weaken(__sig_check) && _weaken(__sig_check)(sigops)) { if (_weaken(__sig_check) && _weaken(__sig_check)(sigops)) {
return eintr(); return eintr();
} }

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/ntspawn.h" #include "libc/calls/ntspawn.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/struct/sigaction.internal.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/pushpop.internal.h" #include "libc/intrin/pushpop.internal.h"
@ -83,6 +84,7 @@ textwindows int ntspawn(
char16_t prog16[PATH_MAX]; char16_t prog16[PATH_MAX];
rc = -1; rc = -1;
block = NULL; block = NULL;
_init_sigchld();
if (__mkntpath(prog, prog16) == -1) return -1; if (__mkntpath(prog, prog16) == -1) return -1;
// we can't call malloc() because we're higher in the topological order // we can't call malloc() because we're higher in the topological order
// we can't call kmalloc() because fork() calls this when kmalloc is locked // we can't call kmalloc() because fork() calls this when kmalloc is locked

View file

@ -34,18 +34,6 @@
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle; __msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
__msabi extern typeof(WriteFile) *const __imp_WriteFile; __msabi extern typeof(WriteFile) *const __imp_WriteFile;
static textwindows unsigned long StrLen(const char *s) {
unsigned long n = 0;
while (*s++) ++n;
return n;
}
static textwindows void Log(const char *s) {
#ifndef NDEBUG
__imp_WriteFile(__imp_GetStdHandle(kNtStdErrorHandle), s, StrLen(s), 0, 0);
#endif
}
static textwindows int GetSig(uint32_t dwCtrlType) { static textwindows int GetSig(uint32_t dwCtrlType) {
switch (dwCtrlType) { switch (dwCtrlType) {
case kNtCtrlCEvent: case kNtCtrlCEvent:
@ -61,11 +49,10 @@ static textwindows int GetSig(uint32_t dwCtrlType) {
} }
} }
__msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) { textwindows bool32 __sig_notify(int sig, int sic) {
// we're on a stack that's owned by win32. to make matters worse, // we're on a stack that's owned by win32. to make matters worse,
// win32 spawns a totally new thread just to invoke this handler. // win32 spawns a totally new thread just to invoke this handler.
int sig = GetSig(dwCtrlType);
if (__sighandrvas[sig] == (uintptr_t)SIG_IGN) { if (__sighandrvas[sig] == (uintptr_t)SIG_IGN) {
return true; return true;
} }
@ -73,7 +60,7 @@ __msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
// if we don't have tls, then we can't hijack a safe stack from a // if we don't have tls, then we can't hijack a safe stack from a
// thread so just try our luck punting the signal to the next i/o // thread so just try our luck punting the signal to the next i/o
if (!__tls_enabled) { if (!__tls_enabled) {
__sig_add(0, sig, SI_KERNEL); __sig_add(0, sig, sic);
return true; return true;
} }
@ -92,7 +79,7 @@ __msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
if (pt->tib->tib_sigmask & (1ull << (sig - 1))) continue; // masked if (pt->tib->tib_sigmask & (1ull << (sig - 1))) continue; // masked
if (pt->flags & PT_BLOCKED) { if (pt->flags & PT_BLOCKED) {
pthread_spin_unlock(&_pthread_lock); pthread_spin_unlock(&_pthread_lock);
__sig_add(0, sig, SI_KERNEL); __sig_add(0, sig, sic);
return true; return true;
} }
} }
@ -111,8 +98,8 @@ __msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
if (tid <= 0) continue; // -1 means spawning, 0 means terminated if (tid <= 0) continue; // -1 means spawning, 0 means terminated
if (pt->tib->tib_sigmask & (1ull << (sig - 1))) continue; // masked if (pt->tib->tib_sigmask & (1ull << (sig - 1))) continue; // masked
pthread_spin_unlock(&_pthread_lock); pthread_spin_unlock(&_pthread_lock);
if (_pthread_signal(pt, sig, SI_KERNEL) == -1) { if (_pthread_signal(pt, sig, sic) == -1) {
__sig_add(0, sig, SI_KERNEL); __sig_add(0, sig, sic);
} }
return true; return true;
} }
@ -121,4 +108,8 @@ __msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
return true; return true;
} }
__msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
return __sig_notify(GetSig(dwCtrlType), SI_KERNEL);
}
#endif /* __x86_64__ */ #endif /* __x86_64__ */

View file

@ -47,6 +47,7 @@ void __sig_pending(sigset_t *);
int __sig_is_applicable(struct Signal *); int __sig_is_applicable(struct Signal *);
bool __sig_deliver(int, int, int, ucontext_t *); bool __sig_deliver(int, int, int, ucontext_t *);
int __sig_tramp(struct Delivery *); int __sig_tramp(struct Delivery *);
bool32 __sig_notify(int, int);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -54,7 +54,6 @@ __static_yoink("strsignal"); // for kprintf()
#if SupportsWindows() #if SupportsWindows()
__static_yoink("_init_onntconsoleevent"); __static_yoink("_init_onntconsoleevent");
__static_yoink("_check_sigwinch");
__static_yoink("_init_wincrash"); __static_yoink("_init_wincrash");
#endif #endif
@ -506,6 +505,9 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
once = true; once = true;
} }
} }
if (IsWindows() && !rc && sig == SIGWINCH) {
_init_sigwinch(); // lazy b/c sigwinch is otherwise ignored
}
} }
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig, DescribeSigaction(0, act), STRACE("sigaction(%G, %s, [%s]) → %d% m", sig, DescribeSigaction(0, act),
DescribeSigaction(rc, oldact), rc); DescribeSigaction(rc, oldact), rc);

View file

@ -16,31 +16,37 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h" #include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h" #include "libc/calls/state.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h" #include "libc/cosmo.h"
#include "libc/nt/enum/wait.h" #include "libc/nt/enum/wait.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h" #include "libc/nt/synchronization.h"
#include "libc/nt/thread.h"
#include "libc/sysv/consts/sa.h" #include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/thread/tls.h"
#include "libc/thread/tls2.internal.h"
#ifdef __x86_64__ #ifdef __x86_64__
static textwindows bool CheckForExitedChildProcess(void) { intptr_t __sigchld_thread;
static atomic_uint __sigchld_once;
static struct CosmoTib __sigchld_tls;
static textwindows bool __sigchld_check(void) {
bool should_signal = false;
for (;;) {
int pids[64]; int pids[64];
uint32_t i, n;
int64_t handles[64]; int64_t handles[64];
if (!(n = __sample_pids(pids, handles, true))) return false; uint32_t n = __sample_pids(pids, handles, true);
i = WaitForMultipleObjects(n, handles, false, 0); if (!n) return should_signal;
if (i == kNtWaitFailed) return false; uint32_t i = WaitForMultipleObjects(n, handles, false, 0);
if (i == kNtWaitTimeout) return false; if (i == kNtWaitFailed) return should_signal;
if (i == kNtWaitTimeout) return should_signal;
i &= ~kNtWaitAbandoned;
if ((__sighandrvas[SIGCHLD] >= kSigactionMinRva) && if ((__sighandrvas[SIGCHLD] >= kSigactionMinRva) &&
(__sighandflags[SIGCHLD] & SA_NOCLDWAIT)) { (__sighandflags[SIGCHLD] & SA_NOCLDWAIT)) {
CloseHandle(handles[i]); CloseHandle(handles[i]);
@ -48,22 +54,27 @@ static textwindows bool CheckForExitedChildProcess(void) {
} else { } else {
g_fds.p[pids[i]].zombie = true; g_fds.p[pids[i]].zombie = true;
} }
return true; should_signal = true;
}
} }
/** static textwindows uint32_t __sigchld_worker(void *arg) {
* Checks to see if SIGCHLD should be raised on Windows. __set_tls_win32(&__sigchld_tls);
* @return true if a signal was raised for (;;) {
* @note yoinked by fork-nt.c if (__sigchld_check()) {
*/ __sig_notify(SIGCHLD, CLD_EXITED);
textwindows void _check_sigchld(void) {
bool should_signal;
__fds_lock();
should_signal = CheckForExitedChildProcess();
__fds_unlock();
if (should_signal) {
__sig_add(0, SIGCHLD, CLD_EXITED);
} }
SleepEx(100, false);
}
return 0;
}
static textwindows void __sigchld_init(void) {
__sigchld_thread = CreateThread(0, 65536, __sigchld_worker, 0, 0, 0);
}
void _init_sigchld(void) {
cosmo_once(&__sigchld_once, __sigchld_init);
} }
#endif /* __x86_64__ */ #endif /* __x86_64__ */

View file

@ -20,18 +20,21 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h" #include "libc/calls/sig.internal.h"
#include "libc/calls/struct/fd.internal.h" #include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/winsize.h" #include "libc/cosmo.h"
#include "libc/calls/struct/winsize.internal.h"
#include "libc/dce.h"
#include "libc/intrin/atomic.h"
#include "libc/nt/console.h" #include "libc/nt/console.h"
#include "libc/nt/struct/consolescreenbufferinfoex.h" #include "libc/nt/struct/consolescreenbufferinfoex.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thread.h"
#include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/thread/tls.h"
#include "libc/thread/tls2.internal.h"
#ifdef __x86_64__ #ifdef __x86_64__
static atomic_uint __win_winsize; intptr_t __sigwinch_thread;
static unsigned __sigwinch_size;
static atomic_uint __sigwinch_once;
static struct CosmoTib __sigwinch_tls;
static textwindows unsigned __get_console_size(void) { static textwindows unsigned __get_console_size(void) {
for (int fd = 1; fd < 10; ++fd) { for (int fd = 1; fd < 10; ++fd) {
@ -51,20 +54,27 @@ static textwindows unsigned __get_console_size(void) {
return -1u; return -1u;
} }
textwindows void _check_sigwinch(void) { static textwindows uint32_t __sigwinch_worker(void *arg) {
unsigned old = atomic_load_explicit(&__win_winsize, memory_order_acquire); __set_tls_win32(&__sigwinch_tls);
if (old == -1u) return; for (;;) {
unsigned old = __sigwinch_size;
unsigned neu = __get_console_size(); unsigned neu = __get_console_size();
old = atomic_exchange(&__win_winsize, neu);
if (neu != old) { if (neu != old) {
__sig_add(0, SIGWINCH, SI_KERNEL); __sigwinch_size = neu;
__sig_notify(SIGWINCH, SI_KERNEL);
} }
SleepEx(25, false);
}
return 0;
} }
__attribute__((__constructor__)) static void sigwinch_init(void) { static textwindows void __sigwinch_init(void) {
if (!IsWindows()) return; __sigwinch_size = __get_console_size();
unsigned ws = __get_console_size(); __sigwinch_thread = CreateThread(0, 65536, __sigwinch_worker, 0, 0, 0);
atomic_store_explicit(&__win_winsize, ws, memory_order_release); }
textwindows void _init_sigwinch(void) {
cosmo_once(&__sigwinch_once, __sigwinch_init);
} }
#endif /* __x86_64__ */ #endif /* __x86_64__ */

View file

@ -65,7 +65,11 @@ const char *DescribeSigaction(char[256], int, const struct sigaction *);
void _init_onntconsoleevent(void); void _init_onntconsoleevent(void);
void _init_wincrash(void); void _init_wincrash(void);
void _check_sigwinch(void); void _init_sigwinch(void);
void _init_sigchld(void);
extern intptr_t __sigchld_thread;
extern intptr_t __sigwinch_thread;
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -22,7 +22,6 @@ int64_t ntreturn(uint32_t);
void *GetProcAddressModule(const char *, const char *); void *GetProcAddressModule(const char *, const char *);
void WinMainForked(void); void WinMainForked(void);
void _check_sigalrm(void); void _check_sigalrm(void);
void _check_sigchld(void);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -48,7 +48,6 @@ bool IsRunningUnderMake(void);
char *GetSymbolByAddr(int64_t); char *GetSymbolByAddr(int64_t);
void PrintGarbage(void); void PrintGarbage(void);
void PrintGarbageNumeric(FILE *); void PrintGarbageNumeric(FILE *);
void CheckForMemoryLeaks(void);
void PrintWindowsMemory(const char *, size_t); void PrintWindowsMemory(const char *, size_t);
#ifndef __STRICT_ANSI__ #ifndef __STRICT_ANSI__

View file

@ -65,8 +65,6 @@
#ifdef __x86_64__ #ifdef __x86_64__
__static_yoink("_check_sigchld");
extern int64_t __wincrashearly; extern int64_t __wincrashearly;
bool32 __onntconsoleevent(uint32_t); bool32 __onntconsoleevent(uint32_t);
void sys_setitimer_nt_reset(void); void sys_setitimer_nt_reset(void);

View file

@ -115,6 +115,8 @@ void __paginate(int, const char *);
void _weakfree(void *); void _weakfree(void *);
void *_mapanon(size_t) attributeallocsize((1)) mallocesque; void *_mapanon(size_t) attributeallocsize((1)) mallocesque;
void *_mapshared(size_t) attributeallocsize((1)) mallocesque; void *_mapshared(size_t) attributeallocsize((1)) mallocesque;
void CheckForMemoryLeaks(void);
void CheckForFileLeaks(void);
void __enable_threads(void); void __enable_threads(void);
void __oom_hook(size_t); void __oom_hook(size_t);
bool _isheap(void *); bool _isheap(void *);

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- 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 vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -17,81 +17,43 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/promises.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/f.h"
// TODO(jart): Delete? void CheckForFileLeaks(void) {
char msg[512];
STATIC_STACK_ALIGN(GetStackSize()); char *p = msg;
char *pe = msg + 256;
static char stacklog[1024]; bool gotsome = false;
for (int fd = 3; fd < 200; ++fd) {
dontasan size_t GetStackUsage(char *s, size_t n) { if (fcntl(fd, F_GETFL) != -1) {
// RHEL5 MAP_GROWSDOWN seems to only grow to 68kb :'( if (!gotsome) {
// So we count non-zero bytes down from the top p = stpcpy(p, program_invocation_short_name);
// First clear 64 bytes is considered the end p = stpcpy(p, ": FILE DESCRIPTOR LEAKS:");
long *p; gotsome = true;
size_t got;
p = (long *)(s + n);
got = 0;
for (;;) {
p -= 8;
if (p[0] | p[1] | p[2] | p[3] | p[4] | p[5] | p[6] | p[7]) {
++got;
} else {
break;
} }
} if (p + 1 + 12 + 1 < pe) {
return got * 8 * sizeof(long);
}
static textexit void LogStackUse(void) {
bool quote;
char *p, *q;
int i, e, fd;
size_t n, usage;
if (!PLEDGED(STDIO) || !PLEDGED(WPATH) || !PLEDGED(CPATH)) return;
usage = GetStackUsage((char *)GetStackAddr(), GetStackSize());
e = errno;
if ((fd = open(stacklog, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, 0644)) !=
-1) {
p = FormatUint64(stacklog, usage);
for (i = 0; i < __argc; ++i) {
n = strlen(__argv[i]);
if ((q = memchr(__argv[i], '\n', n))) n = q - __argv[i];
if (p - stacklog + 1 + 1 + n + 1 + 1 < sizeof(stacklog)) {
quote = !!memchr(__argv[i], ' ', n);
*p++ = ' '; *p++ = ' ';
if (quote) *p++ = '\''; p = FormatInt32(p, fd);
p = mempcpy(p, __argv[i], n);
if (quote) *p++ = '\'';
} else { } else {
break; break;
} }
} }
}
if (gotsome) {
char proc[64];
char *p = proc;
*p++ = '\n'; *p++ = '\n';
write(fd, stacklog, p - stacklog); *p = 0;
close(fd); write(2, msg, p - msg);
} p = stpcpy(p, "ls -hal /proc/");
errno = e; p = FormatInt32(p, getpid());
} p = stpcpy(p, "/fd");
system(proc);
static textstartup void LogStackUseInit(void) { exit(1);
if (!PLEDGED(WPATH)) return;
if (isdirectory("o/" MODE) &&
getcwd(stacklog, sizeof(stacklog) - strlen("/o/" MODE "/stack.log"))) {
strcat(stacklog, "/o/" MODE "/stack.log");
atexit(LogStackUse);
} }
} }
const void *const stack_usage_logging[] initarray = {
LogStackUseInit,
};

View file

@ -71,7 +71,6 @@ Flags:\n\
__static_yoink("__die"); __static_yoink("__die");
__static_yoink("GetSymbolByAddr"); __static_yoink("GetSymbolByAddr");
__static_yoink("testlib_quota_handlers"); __static_yoink("testlib_quota_handlers");
__static_yoink("stack_usage_logging");
static bool runbenchmarks_; static bool runbenchmarks_;

View file

@ -416,6 +416,8 @@ void PrintProgramOutput(struct Client *client) {
void FreeClient(struct Client *client) { void FreeClient(struct Client *client) {
DEBUF("FreeClient"); DEBUF("FreeClient");
Close(&client->pipe[1]);
Close(&client->pipe[0]);
if (client->pid) { if (client->pid) {
kill(client->pid, SIGHUP); kill(client->pid, SIGHUP);
waitpid(client->pid, 0, 0); waitpid(client->pid, 0, 0);
@ -520,6 +522,8 @@ void *ClientWorker(void *arg) {
// spawn the program // spawn the program
int etxtbsy_tries = 0; int etxtbsy_tries = 0;
RetryOnEtxtbsyRaceCondition: RetryOnEtxtbsyRaceCondition:
Close(&client->pipe[1]);
Close(&client->pipe[0]);
if (etxtbsy_tries++) { if (etxtbsy_tries++) {
if (etxtbsy_tries == 24) { // ~30 seconds if (etxtbsy_tries == 24) { // ~30 seconds
WARNF("%s failed to spawn on %s due because either (1) the ETXTBSY race " WARNF("%s failed to spawn on %s due because either (1) the ETXTBSY race "
@ -547,8 +551,6 @@ RetryOnEtxtbsyRaceCondition:
posix_spawn_file_actions_adddup2(&spawnfila, client->pipe[1], 2); posix_spawn_file_actions_adddup2(&spawnfila, client->pipe[1], 2);
err = posix_spawn(&client->pid, exe, &spawnfila, &spawnattr, args, environ); err = posix_spawn(&client->pid, exe, &spawnfila, &spawnattr, args, environ);
if (err) { if (err) {
Close(&client->pipe[1]);
Close(&client->pipe[0]);
if (err == ETXTBSY) { if (err == ETXTBSY) {
goto RetryOnEtxtbsyRaceCondition; goto RetryOnEtxtbsyRaceCondition;
} }
@ -782,8 +784,8 @@ int main(int argc, char *argv[]) {
Serve(); Serve();
free(g_psk); free(g_psk);
#if IsModeDbg() #if IsModeDbg()
void CheckForMemoryLeaks(void);
CheckForMemoryLeaks(); CheckForMemoryLeaks();
CheckForFileLeaks();
#endif #endif
pthread_exit(0); pthread_exit(0);
} }