mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Improve performance and remove fd leaks
This commit is contained in:
parent
26e254fb4d
commit
1965d7488e
17 changed files with 131 additions and 159 deletions
|
@ -69,6 +69,8 @@ $(LIBC_CALLS_A).pkg: \
|
|||
# we're on a stack owned by win32 without tls
|
||||
o/$(MODE)/libc/calls/foist.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/wincrash.o \
|
||||
o/$(MODE)/libc/calls/ntcontext2linux.o: private \
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/calls/struct/sigaction.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
@ -166,6 +167,8 @@ keywords int sys_execve_nt(const char *program, char *const argv[],
|
|||
|
||||
// kill siblings
|
||||
sys_execve_killer();
|
||||
PurgeThread(*_weaken(__sigchld_thread));
|
||||
PurgeThread(*_weaken(__sigwinch_thread));
|
||||
|
||||
// close win32 handles for memory mappings
|
||||
// unlike fork calling execve destroys all memory
|
||||
|
|
|
@ -16,19 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/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/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/struct/windowplacement.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
@ -51,14 +44,6 @@ textwindows int _check_interrupts(int sigops) {
|
|||
if (__tls_enabled) {
|
||||
__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)) {
|
||||
return eintr();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/struct/sigaction.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pushpop.internal.h"
|
||||
|
@ -83,6 +84,7 @@ textwindows int ntspawn(
|
|||
char16_t prog16[PATH_MAX];
|
||||
rc = -1;
|
||||
block = NULL;
|
||||
_init_sigchld();
|
||||
if (__mkntpath(prog, prog16) == -1) return -1;
|
||||
// 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
|
||||
|
|
|
@ -34,18 +34,6 @@
|
|||
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
|
||||
__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) {
|
||||
switch (dwCtrlType) {
|
||||
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,
|
||||
// win32 spawns a totally new thread just to invoke this handler.
|
||||
int sig = GetSig(dwCtrlType);
|
||||
if (__sighandrvas[sig] == (uintptr_t)SIG_IGN) {
|
||||
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
|
||||
// thread so just try our luck punting the signal to the next i/o
|
||||
if (!__tls_enabled) {
|
||||
__sig_add(0, sig, SI_KERNEL);
|
||||
__sig_add(0, sig, sic);
|
||||
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->flags & PT_BLOCKED) {
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
__sig_add(0, sig, SI_KERNEL);
|
||||
__sig_add(0, sig, sic);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -111,8 +98,8 @@ __msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
|
|||
if (tid <= 0) continue; // -1 means spawning, 0 means terminated
|
||||
if (pt->tib->tib_sigmask & (1ull << (sig - 1))) continue; // masked
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
if (_pthread_signal(pt, sig, SI_KERNEL) == -1) {
|
||||
__sig_add(0, sig, SI_KERNEL);
|
||||
if (_pthread_signal(pt, sig, sic) == -1) {
|
||||
__sig_add(0, sig, sic);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -121,4 +108,8 @@ __msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
|
|||
return true;
|
||||
}
|
||||
|
||||
__msabi textwindows bool32 __onntconsoleevent(uint32_t dwCtrlType) {
|
||||
return __sig_notify(GetSig(dwCtrlType), SI_KERNEL);
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -47,6 +47,7 @@ void __sig_pending(sigset_t *);
|
|||
int __sig_is_applicable(struct Signal *);
|
||||
bool __sig_deliver(int, int, int, ucontext_t *);
|
||||
int __sig_tramp(struct Delivery *);
|
||||
bool32 __sig_notify(int, int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -54,7 +54,6 @@ __static_yoink("strsignal"); // for kprintf()
|
|||
|
||||
#if SupportsWindows()
|
||||
__static_yoink("_init_onntconsoleevent");
|
||||
__static_yoink("_check_sigwinch");
|
||||
__static_yoink("_init_wincrash");
|
||||
#endif
|
||||
|
||||
|
@ -506,6 +505,9 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
|||
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),
|
||||
DescribeSigaction(rc, oldact), rc);
|
||||
|
|
|
@ -16,31 +16,37 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/siginfo.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/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/tls2.internal.h"
|
||||
#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];
|
||||
uint32_t i, n;
|
||||
int64_t handles[64];
|
||||
if (!(n = __sample_pids(pids, handles, true))) return false;
|
||||
i = WaitForMultipleObjects(n, handles, false, 0);
|
||||
if (i == kNtWaitFailed) return false;
|
||||
if (i == kNtWaitTimeout) return false;
|
||||
uint32_t n = __sample_pids(pids, handles, true);
|
||||
if (!n) return should_signal;
|
||||
uint32_t i = WaitForMultipleObjects(n, handles, false, 0);
|
||||
if (i == kNtWaitFailed) return should_signal;
|
||||
if (i == kNtWaitTimeout) return should_signal;
|
||||
i &= ~kNtWaitAbandoned;
|
||||
if ((__sighandrvas[SIGCHLD] >= kSigactionMinRva) &&
|
||||
(__sighandflags[SIGCHLD] & SA_NOCLDWAIT)) {
|
||||
CloseHandle(handles[i]);
|
||||
|
@ -48,22 +54,27 @@ static textwindows bool CheckForExitedChildProcess(void) {
|
|||
} else {
|
||||
g_fds.p[pids[i]].zombie = true;
|
||||
}
|
||||
return true;
|
||||
should_signal = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if SIGCHLD should be raised on Windows.
|
||||
* @return true if a signal was raised
|
||||
* @note yoinked by fork-nt.c
|
||||
*/
|
||||
textwindows void _check_sigchld(void) {
|
||||
bool should_signal;
|
||||
__fds_lock();
|
||||
should_signal = CheckForExitedChildProcess();
|
||||
__fds_unlock();
|
||||
if (should_signal) {
|
||||
__sig_add(0, SIGCHLD, CLD_EXITED);
|
||||
static textwindows uint32_t __sigchld_worker(void *arg) {
|
||||
__set_tls_win32(&__sigchld_tls);
|
||||
for (;;) {
|
||||
if (__sigchld_check()) {
|
||||
__sig_notify(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__ */
|
||||
|
|
|
@ -20,18 +20,21 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/winsize.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/nt/console.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/sig.h"
|
||||
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/tls2.internal.h"
|
||||
#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) {
|
||||
for (int fd = 1; fd < 10; ++fd) {
|
||||
|
@ -51,20 +54,27 @@ static textwindows unsigned __get_console_size(void) {
|
|||
return -1u;
|
||||
}
|
||||
|
||||
textwindows void _check_sigwinch(void) {
|
||||
unsigned old = atomic_load_explicit(&__win_winsize, memory_order_acquire);
|
||||
if (old == -1u) return;
|
||||
static textwindows uint32_t __sigwinch_worker(void *arg) {
|
||||
__set_tls_win32(&__sigwinch_tls);
|
||||
for (;;) {
|
||||
unsigned old = __sigwinch_size;
|
||||
unsigned neu = __get_console_size();
|
||||
old = atomic_exchange(&__win_winsize, neu);
|
||||
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) {
|
||||
if (!IsWindows()) return;
|
||||
unsigned ws = __get_console_size();
|
||||
atomic_store_explicit(&__win_winsize, ws, memory_order_release);
|
||||
static textwindows void __sigwinch_init(void) {
|
||||
__sigwinch_size = __get_console_size();
|
||||
__sigwinch_thread = CreateThread(0, 65536, __sigwinch_worker, 0, 0, 0);
|
||||
}
|
||||
|
||||
textwindows void _init_sigwinch(void) {
|
||||
cosmo_once(&__sigwinch_once, __sigwinch_init);
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -65,7 +65,11 @@ const char *DescribeSigaction(char[256], int, const struct sigaction *);
|
|||
|
||||
void _init_onntconsoleevent(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_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -22,7 +22,6 @@ int64_t ntreturn(uint32_t);
|
|||
void *GetProcAddressModule(const char *, const char *);
|
||||
void WinMainForked(void);
|
||||
void _check_sigalrm(void);
|
||||
void _check_sigchld(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -48,7 +48,6 @@ bool IsRunningUnderMake(void);
|
|||
char *GetSymbolByAddr(int64_t);
|
||||
void PrintGarbage(void);
|
||||
void PrintGarbageNumeric(FILE *);
|
||||
void CheckForMemoryLeaks(void);
|
||||
void PrintWindowsMemory(const char *, size_t);
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
|
|
|
@ -65,8 +65,6 @@
|
|||
|
||||
#ifdef __x86_64__
|
||||
|
||||
__static_yoink("_check_sigchld");
|
||||
|
||||
extern int64_t __wincrashearly;
|
||||
bool32 __onntconsoleevent(uint32_t);
|
||||
void sys_setitimer_nt_reset(void);
|
||||
|
|
|
@ -115,6 +115,8 @@ void __paginate(int, const char *);
|
|||
void _weakfree(void *);
|
||||
void *_mapanon(size_t) attributeallocsize((1)) mallocesque;
|
||||
void *_mapshared(size_t) attributeallocsize((1)) mallocesque;
|
||||
void CheckForMemoryLeaks(void);
|
||||
void CheckForFileLeaks(void);
|
||||
void __enable_threads(void);
|
||||
void __oom_hook(size_t);
|
||||
bool _isheap(void *);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 │
|
||||
│ Copyright 2023 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 │
|
||||
|
@ -17,81 +17,43 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.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/stack.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
|
||||
// TODO(jart): Delete?
|
||||
|
||||
STATIC_STACK_ALIGN(GetStackSize());
|
||||
|
||||
static char stacklog[1024];
|
||||
|
||||
dontasan size_t GetStackUsage(char *s, size_t n) {
|
||||
// RHEL5 MAP_GROWSDOWN seems to only grow to 68kb :'(
|
||||
// So we count non-zero bytes down from the top
|
||||
// First clear 64 bytes is considered the end
|
||||
long *p;
|
||||
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;
|
||||
void CheckForFileLeaks(void) {
|
||||
char msg[512];
|
||||
char *p = msg;
|
||||
char *pe = msg + 256;
|
||||
bool gotsome = false;
|
||||
for (int fd = 3; fd < 200; ++fd) {
|
||||
if (fcntl(fd, F_GETFL) != -1) {
|
||||
if (!gotsome) {
|
||||
p = stpcpy(p, program_invocation_short_name);
|
||||
p = stpcpy(p, ": FILE DESCRIPTOR LEAKS:");
|
||||
gotsome = true;
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (p + 1 + 12 + 1 < pe) {
|
||||
*p++ = ' ';
|
||||
if (quote) *p++ = '\'';
|
||||
p = mempcpy(p, __argv[i], n);
|
||||
if (quote) *p++ = '\'';
|
||||
p = FormatInt32(p, fd);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gotsome) {
|
||||
char proc[64];
|
||||
char *p = proc;
|
||||
*p++ = '\n';
|
||||
write(fd, stacklog, p - stacklog);
|
||||
close(fd);
|
||||
}
|
||||
errno = e;
|
||||
}
|
||||
|
||||
static textstartup void LogStackUseInit(void) {
|
||||
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);
|
||||
*p = 0;
|
||||
write(2, msg, p - msg);
|
||||
p = stpcpy(p, "ls -hal /proc/");
|
||||
p = FormatInt32(p, getpid());
|
||||
p = stpcpy(p, "/fd");
|
||||
system(proc);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const void *const stack_usage_logging[] initarray = {
|
||||
LogStackUseInit,
|
||||
};
|
|
@ -71,7 +71,6 @@ Flags:\n\
|
|||
__static_yoink("__die");
|
||||
__static_yoink("GetSymbolByAddr");
|
||||
__static_yoink("testlib_quota_handlers");
|
||||
__static_yoink("stack_usage_logging");
|
||||
|
||||
static bool runbenchmarks_;
|
||||
|
||||
|
|
|
@ -416,6 +416,8 @@ void PrintProgramOutput(struct Client *client) {
|
|||
|
||||
void FreeClient(struct Client *client) {
|
||||
DEBUF("FreeClient");
|
||||
Close(&client->pipe[1]);
|
||||
Close(&client->pipe[0]);
|
||||
if (client->pid) {
|
||||
kill(client->pid, SIGHUP);
|
||||
waitpid(client->pid, 0, 0);
|
||||
|
@ -520,6 +522,8 @@ void *ClientWorker(void *arg) {
|
|||
// spawn the program
|
||||
int etxtbsy_tries = 0;
|
||||
RetryOnEtxtbsyRaceCondition:
|
||||
Close(&client->pipe[1]);
|
||||
Close(&client->pipe[0]);
|
||||
if (etxtbsy_tries++) {
|
||||
if (etxtbsy_tries == 24) { // ~30 seconds
|
||||
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);
|
||||
err = posix_spawn(&client->pid, exe, &spawnfila, &spawnattr, args, environ);
|
||||
if (err) {
|
||||
Close(&client->pipe[1]);
|
||||
Close(&client->pipe[0]);
|
||||
if (err == ETXTBSY) {
|
||||
goto RetryOnEtxtbsyRaceCondition;
|
||||
}
|
||||
|
@ -782,8 +784,8 @@ int main(int argc, char *argv[]) {
|
|||
Serve();
|
||||
free(g_psk);
|
||||
#if IsModeDbg()
|
||||
void CheckForMemoryLeaks(void);
|
||||
CheckForMemoryLeaks();
|
||||
CheckForFileLeaks();
|
||||
#endif
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue