mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 06:48:31 +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,54 +16,65 @@
|
|||
│ 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) {
|
||||
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;
|
||||
if ((__sighandrvas[SIGCHLD] >= kSigactionMinRva) &&
|
||||
(__sighandflags[SIGCHLD] & SA_NOCLDWAIT)) {
|
||||
CloseHandle(handles[i]);
|
||||
__releasefd(pids[i]);
|
||||
} else {
|
||||
g_fds.p[pids[i]].zombie = true;
|
||||
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];
|
||||
int64_t handles[64];
|
||||
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]);
|
||||
__releasefd(pids[i]);
|
||||
} else {
|
||||
g_fds.p[pids[i]].zombie = true;
|
||||
}
|
||||
should_signal = true;
|
||||
}
|
||||
return 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;
|
||||
unsigned neu = __get_console_size();
|
||||
old = atomic_exchange(&__win_winsize, neu);
|
||||
if (neu != old) {
|
||||
__sig_add(0, SIGWINCH, SI_KERNEL);
|
||||
static textwindows uint32_t __sigwinch_worker(void *arg) {
|
||||
__set_tls_win32(&__sigwinch_tls);
|
||||
for (;;) {
|
||||
unsigned old = __sigwinch_size;
|
||||
unsigned neu = __get_console_size();
|
||||
if (neu != old) {
|
||||
__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) */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue