From 4ddfc47d6ebc2088edab78cbc43bfca800b5fc35 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 12 Jun 2022 09:37:17 -0700 Subject: [PATCH] Make some more fixups --- build/bootstrap/mkdeps.com | Bin 94208 -> 98304 bytes libc/intrin/cxaatexit.c | 10 +-- libc/intrin/cxafinalize.c | 14 +++- libc/intrin/cxalock.c | 21 +++++ libc/intrin/intrin.mk | 18 ---- libc/intrin/kprintf.greg.c | 79 ++---------------- libc/intrin/kprintf.h | 3 - libc/intrin/pthread_mutex_lock.c | 2 +- libc/intrin/pthread_mutex_unlock.c | 2 +- libc/runtime/cxaatexit.internal.h | 5 ++ libc/runtime/fork-nt.c | 9 +- libc/runtime/ismemtracked.greg.c | 1 + libc/runtime/runtime.h | 2 +- libc/runtime/winmain.greg.c | 3 +- test/libc/intrin/kprintf_test.c | 31 ++++--- tool/build/mkdeps.c | 9 +- tool/build/runit.c | 129 +---------------------------- tool/net/redbean.c | 2 +- 18 files changed, 81 insertions(+), 259 deletions(-) create mode 100644 libc/intrin/cxalock.c diff --git a/build/bootstrap/mkdeps.com b/build/bootstrap/mkdeps.com index e44772d330dae5017c48d4d4aadf675e3693f260..f247a5756d52b5a86517d7c3b2eeef720d14f4c2 100755 GIT binary patch delta 33092 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 diff --git a/libc/intrin/cxaatexit.c b/libc/intrin/cxaatexit.c index c39d609ac..061a38d9f 100644 --- a/libc/intrin/cxaatexit.c +++ b/libc/intrin/cxaatexit.c @@ -19,8 +19,6 @@ #include "libc/assert.h" #include "libc/bits/weaken.h" #include "libc/calls/strace.internal.h" -#include "libc/intrin/pthread.h" -#include "libc/intrin/spinlock.h" #include "libc/macros.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/bsr.h" @@ -30,8 +28,6 @@ STATIC_YOINK("__cxa_finalize"); -static pthread_mutex_t __cxa_lock; - /** * Adds global destructor. * @@ -51,7 +47,7 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) { unsigned i; struct CxaAtexitBlock *b, *b2; _Static_assert(ATEXIT_MAX == CHAR_BIT * sizeof(b->mask), ""); - pthread_mutex_lock(&__cxa_lock); + __cxa_lock(); b = __cxa_blocks.p; if (!b) b = __cxa_blocks.p = &__cxa_blocks.root; if (!~b->mask) { @@ -60,7 +56,7 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) { b2->next = b; __cxa_blocks.p = b = b2; } else { - pthread_mutex_unlock(&__cxa_lock); + __cxa_unlock(); return enomem(); } } @@ -70,6 +66,6 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) { b->p[i].fp = fp; b->p[i].arg = arg; b->p[i].pred = pred; - pthread_mutex_unlock(&__cxa_lock); + __cxa_unlock(); return 0; } diff --git a/libc/intrin/cxafinalize.c b/libc/intrin/cxafinalize.c index ca9796b05..9ffea93f2 100644 --- a/libc/intrin/cxafinalize.c +++ b/libc/intrin/cxafinalize.c @@ -34,9 +34,12 @@ * @param pred can be null to match all */ void __cxa_finalize(void *pred) { + void *fp, *arg; unsigned i, mask; struct CxaAtexitBlock *b, *b2; StartOver: + __cxa_lock(); +StartOverLocked: if ((b = __cxa_blocks.p)) { for (;;) { mask = b->mask; @@ -45,9 +48,11 @@ StartOver: mask &= ~(1u << i); if (!pred || pred == b->p[i].pred) { b->mask &= ~(1u << i); - if (b->p[i].fp) { - STRACE("__cxa_finalize(%t, %p)", b->p[i].fp, b->p[i].arg); - ((void (*)(void *))b->p[i].fp)(b->p[i].arg); + if ((fp = b->p[i].fp)) { + arg = b->p[i].arg; + __cxa_unlock(); + STRACE("__cxa_finalize(%t, %p)", fp, arg); + ((void (*)(void *))fp)(arg); goto StartOver; } } @@ -61,7 +66,7 @@ StartOver: } } __cxa_blocks.p = b2; - goto StartOver; + goto StartOverLocked; } else { if (b->next) { b = b->next; @@ -71,4 +76,5 @@ StartOver: } } } + __cxa_unlock(); } diff --git a/libc/intrin/cxalock.c b/libc/intrin/cxalock.c new file mode 100644 index 000000000..a1e56afaf --- /dev/null +++ b/libc/intrin/cxalock.c @@ -0,0 +1,21 @@ +/*-*- 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 2022 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 │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/cxaatexit.internal.h" + +pthread_mutex_t __cxa_lock_obj; diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk index 6bf9df84f..d9225e243 100644 --- a/libc/intrin/intrin.mk +++ b/libc/intrin/intrin.mk @@ -42,10 +42,6 @@ $(LIBC_INTRIN_A).pkg: \ $(LIBC_INTRIN_A_OBJS) \ $(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg) -$(LIBC_INTRIN_A_OBJS): \ - OVERRIDE_CFLAGS += \ - -foptimize-sibling-calls - # we can't use asan and ubsan because: # this is asan and ubsan o/$(MODE)/libc/intrin/asan.o \ @@ -76,20 +72,6 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: \ -fno-sanitize=all \ -fno-stack-protector -# we can't use compiler magic because: -# spinlocks are called very early in initialization -# e.g. __cxa_atexit() -o/$(MODE)/libc/intrin/gettid.greg.o \ -o/$(MODE)/libc/intrin/_trylock_debug_4.o \ -o/$(MODE)/libc/intrin/_spinlock_debug_4.o: \ - OVERRIDE_CFLAGS += \ - -fwrapv \ - -x-no-pg \ - -mno-fentry \ - -ffreestanding \ - -fno-sanitize=all \ - -fno-stack-protector - o/$(MODE)/libc/intrin/tls.greg.o \ o/$(MODE)/libc/intrin/exit.greg.o \ o/$(MODE)/libc/intrin/exit1.greg.o \ diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index 82f3395f2..2e94ea839 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -55,36 +55,6 @@ extern hidden struct SymbolTable *__symtab; -struct Timestamps { - unsigned long long birth; - unsigned long long start; -}; - -unsigned long long __kbirth; // see fork-nt.c - -privileged static struct Timestamps kenter(void) { - struct Timestamps ts; - ts.start = rdtsc(); - ts.birth = __kbirth; - if (!ts.birth) { - ts.birth = kStartTsc; - if (!ts.birth) ts.birth = 1; - _lockcmpxchg(&__kbirth, 0, ts.birth); - } - return ts; -} - -privileged static void kleave(struct Timestamps ts) { - uint64_t finish, elapse, adjust; - finish = rdtsc(); - elapse = unsignedsubtract(finish, ts.start); - adjust = ts.birth + elapse; - if (!adjust) adjust = 1; - if (__kbirth == ts.birth) { - _lockcmpxchg(&__kbirth, ts.birth, adjust); // ignore overlapping intervals - } -} - privileged static inline char *kadvance(char *p, char *e, long n) { intptr_t t = (intptr_t)p; if (__builtin_add_overflow(t, n, &t)) t = (intptr_t)e; @@ -213,8 +183,8 @@ privileged static void klog(const char *b, size_t n) { } } -privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, - struct Timestamps ts) { +privileged static size_t kformat(char *b, size_t n, const char *fmt, + va_list va) { int si; wint_t t, u; const char *abet; @@ -333,7 +303,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, continue; case 'T': - x = ClocksToNanos(ts.start, ts.birth) % 86400000000000; + x = ClocksToNanos(rdtsc(), kStartTsc) % 86400000000000; goto FormatUnsigned; case 'P': @@ -766,37 +736,8 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, privileged size_t ksnprintf(char *b, size_t n, const char *fmt, ...) { size_t m; va_list v; - struct Timestamps t; - t = kenter(); va_start(v, fmt); - m = kformat(b, n, fmt, v, t); - va_end(v); - kleave(t); - return m; -} - -/** - * Privileged snprintf() w/o timestamp feature. - * - * This provides a marginal performance boost, but it means %T can no - * longer be used. - * - * snprintf(".") l: 25𝑐 8𝑛𝑠 - * kusnprintf(".") l: 22𝑐 7𝑛𝑠 - * ksnprintf(".") l: 54𝑐 17𝑛𝑠 - * - * @param b is buffer, and guaranteed a NUL-terminator if `n>0` - * @param n is number of bytes available in buffer - * @return length of output excluding NUL, which may exceed `n` - * @see kprintf() for documentation - * @asyncsignalsafe - * @vforksafe - */ -privileged size_t kusnprintf(char *b, size_t n, const char *fmt, ...) { - size_t m; - va_list v; - va_start(v, fmt); - m = kformat(b, n, fmt, v, (struct Timestamps){0}); + m = kformat(b, n, fmt, v); va_end(v); return m; } @@ -812,12 +753,7 @@ privileged size_t kusnprintf(char *b, size_t n, const char *fmt, ...) { * @vforksafe */ privileged size_t kvsnprintf(char *b, size_t n, const char *fmt, va_list v) { - size_t m; - struct Timestamps t; - t = kenter(); - m = kformat(b, n, fmt, v, t); - kleave(t); - return m; + return kformat(b, n, fmt, v); } /** @@ -830,12 +766,9 @@ privileged size_t kvsnprintf(char *b, size_t n, const char *fmt, va_list v) { privileged void kvprintf(const char *fmt, va_list v) { size_t n; char b[4000]; - struct Timestamps t; if (!v) return; - t = kenter(); - n = kformat(b, sizeof(b), fmt, v, t); + n = kformat(b, sizeof(b), fmt, v); klog(b, MIN(n, sizeof(b) - 1)); - kleave(t); } /** diff --git a/libc/intrin/kprintf.h b/libc/intrin/kprintf.h index 63646e6a3..5bc910675 100644 --- a/libc/intrin/kprintf.h +++ b/libc/intrin/kprintf.h @@ -3,11 +3,8 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -extern unsigned long long __kbirth; - void kprintf(const char *, ...); size_t ksnprintf(char *, size_t, const char *, ...); -size_t kusnprintf(char *, size_t, const char *, ...); void kvprintf(const char *, va_list); size_t kvsnprintf(char *, size_t, const char *, va_list); bool kisdangerous(const void *); diff --git a/libc/intrin/pthread_mutex_lock.c b/libc/intrin/pthread_mutex_lock.c index 3fe72b281..53031d1c5 100644 --- a/libc/intrin/pthread_mutex_lock.c +++ b/libc/intrin/pthread_mutex_lock.c @@ -26,7 +26,7 @@ /** * Acquires mutex. */ -int pthread_mutex_lock(pthread_mutex_t *mutex) { +noasan noubsan int pthread_mutex_lock(pthread_mutex_t *mutex) { int me, owner; unsigned tries; if (__threaded) { diff --git a/libc/intrin/pthread_mutex_unlock.c b/libc/intrin/pthread_mutex_unlock.c index 44912866e..66e6e5f2e 100644 --- a/libc/intrin/pthread_mutex_unlock.c +++ b/libc/intrin/pthread_mutex_unlock.c @@ -27,7 +27,7 @@ /** * Releases mutex. */ -int pthread_mutex_unlock(pthread_mutex_t *mutex) { +noasan noubsan int pthread_mutex_unlock(pthread_mutex_t *mutex) { int owner; bool shouldunlock; assert(mutex->reent > 0); diff --git a/libc/runtime/cxaatexit.internal.h b/libc/runtime/cxaatexit.internal.h index 9da432b53..f08184c4b 100644 --- a/libc/runtime/cxaatexit.internal.h +++ b/libc/runtime/cxaatexit.internal.h @@ -1,5 +1,6 @@ #ifndef COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_ #define COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_ +#include "libc/intrin/pthread.h" #include "libc/stdio/stdio.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -16,10 +17,14 @@ struct CxaAtexitBlocks { } * p, root; }; +extern pthread_mutex_t __cxa_lock_obj; extern struct CxaAtexitBlocks __cxa_blocks; void __cxa_printexits(FILE *, void *); +#define __cxa_lock() pthread_mutex_lock(&__cxa_lock_obj) +#define __cxa_unlock() pthread_mutex_unlock(&__cxa_lock_obj) + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_ */ diff --git a/libc/runtime/fork-nt.c b/libc/runtime/fork-nt.c index d3d9f827c..ee7047383 100644 --- a/libc/runtime/fork-nt.c +++ b/libc/runtime/fork-nt.c @@ -139,12 +139,11 @@ textwindows void WinMainForked(void) { char *addr, *shad; struct DirectMap dm; uint64_t size, upsize; + int64_t oncrash, savetsc; struct MemoryInterval *maps; char16_t fvar[21 + 1 + 21 + 1]; - int64_t oncrash, savetsc, savebir; uint32_t i, varlen, oldprot, savepid; long mapcount, mapcapacity, specialz; - extern uint64_t ts asm("kStartTsc"); // check to see if the process was actually forked // this variable should have the pipe handle numba @@ -198,13 +197,11 @@ textwindows void WinMainForked(void) { // read the .data and .bss program image sections savepid = __pid; - savebir = __kbirth; - savetsc = ts; + savetsc = kStartTsc; ReadOrDie(reader, __data_start, __data_end - __data_start); ReadOrDie(reader, __bss_start, __bss_end - __bss_start); __pid = savepid; - __kbirth = savebir; - ts = savetsc; + kStartTsc = savetsc; // apply fixups and reapply memory protections _mmi.p = maps; diff --git a/libc/runtime/ismemtracked.greg.c b/libc/runtime/ismemtracked.greg.c index becbd54aa..eb7c658c0 100644 --- a/libc/runtime/ismemtracked.greg.c +++ b/libc/runtime/ismemtracked.greg.c @@ -31,6 +31,7 @@ static inline bool IsMemtrackedImpl(int x, int y) { } bool IsMemtracked(int x, int y) { + /* assumes __mmi_lock() is held */ bool res; res = IsMemtrackedImpl(x, y); return res; diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 1ca227780..e04d2cfe6 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -20,7 +20,7 @@ extern _Atomic(int) __strace; /* SYS */ extern char *program_invocation_name; /* RII */ extern char *program_invocation_short_name; /* RII */ extern uint64_t __syscount; /* RII */ -extern const uint64_t kStartTsc; /* RII */ +extern uint64_t kStartTsc; /* RII */ extern const char kTmpPath[]; /* RII */ extern const char kNtSystemDirectory[]; /* RII */ extern const char kNtWindowsDirectory[]; /* RII */ diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index de60e3d78..e3d50ae20 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -275,9 +275,8 @@ __msabi textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance, const char *lpCmdLine, int64_t nCmdShow) { const char16_t *cmdline; extern char os asm("__hostos"); - extern uint64_t ts asm("kStartTsc"); os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */ - ts = rdtsc(); + kStartTsc = rdtsc(); __pid = GetCurrentProcessId(); #if !IsTiny() __wincrashearly = AddVectoredExceptionHandler(1, (void *)OnEarlyWinCrash); diff --git a/test/libc/intrin/kprintf_test.c b/test/libc/intrin/kprintf_test.c index 7618d68da..6ef0286d8 100644 --- a/test/libc/intrin/kprintf_test.c +++ b/test/libc/intrin/kprintf_test.c @@ -384,28 +384,33 @@ BENCH(printf, bench) { char b[128]; int snprintf_(char *, size_t, const char *, ...) asm("snprintf"); EZBENCH2("ksnprintf fmt", donothing, ksnprintf(b, 128, ".")); - EZBENCH2("kusnprintf fmt", donothing, kusnprintf(b, 128, ".")); EZBENCH2("snprintf fmt", donothing, snprintf_(b, 128, ".")); - EZBENCH2("kusnprintf str", donothing, - kusnprintf(b, 128, "%s\n", "hello world")); + EZBENCH2("ksnprintf str", donothing, + ksnprintf(b, 128, "%s\n", "hello world")); EZBENCH2("snprintf str", donothing, snprintf_(b, 128, "%s\n", "hello world")); - EZBENCH2("kusnprintf utf8", donothing, - kusnprintf(b, 128, "%s\n", "天地玄黄宇宙洪荒天地玄黄宇宙洪荒")); + EZBENCH2("ksnprintf utf8", donothing, + ksnprintf(b, 128, "%s\n", "天地玄黄宇宙洪荒天地玄黄宇宙洪荒")); EZBENCH2("snprintf utf8", donothing, snprintf_(b, 128, "%s\n", "天地玄黄宇宙洪荒天地玄黄宇宙洪荒")); - EZBENCH2("kusnprintf chinese", donothing, - kusnprintf(b, 128, "%hs\n", u"天地玄黄宇宙洪荒")); + EZBENCH2("ksnprintf chinese", donothing, + ksnprintf(b, 128, "%hs\n", u"天地玄黄宇宙洪荒")); EZBENCH2("snprintf chinese", donothing, snprintf_(b, 128, "%hs\n", u"天地玄黄宇宙洪荒")); - EZBENCH2("kusnprintf astral", donothing, - kusnprintf(b, 128, "%hs\n", u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷")); + EZBENCH2("ksnprintf astral", donothing, + ksnprintf(b, 128, "%hs\n", u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷")); EZBENCH2("snprintf astral", donothing, snprintf_(b, 128, "%hs\n", u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷")); - EZBENCH2("kusnprintf octal", donothing, - kusnprintf(b, 128, "%#lo", ULONG_MAX)); - EZBENCH2("kusnprintf long", donothing, kusnprintf(b, 128, "%ld", LONG_MAX)); + EZBENCH2("ksnprintf octal", donothing, ksnprintf(b, 128, "%#lo", ULONG_MAX)); + EZBENCH2("snprintf octal", donothing, snprintf(b, 128, "%#lo", ULONG_MAX)); + EZBENCH2("ksnprintf long", donothing, ksnprintf(b, 128, "%ld", LONG_MAX)); EZBENCH2("snprintf long", donothing, snprintf_(b, 128, "%ld", LONG_MAX)); - EZBENCH2("kusnprintf thou", donothing, kusnprintf(b, 128, "%'ld", LONG_MAX)); + EZBENCH2("ksnprintf thou", donothing, ksnprintf(b, 128, "%'ld", LONG_MAX)); EZBENCH2("snprintf thou", donothing, snprintf_(b, 128, "%'ld", LONG_MAX)); + EZBENCH2( + "ksnprintf bin", donothing, + ksnprintf(b, 128, "%#.*hhs\n", 8, "\001\002\003\004\005\006\007\008")); + EZBENCH2( + "snprintf bin", donothing, + snprintf(b, 128, "%`'.*hhs\n", 8, "\001\002\003\004\005\006\007\008")); } diff --git a/tool/build/mkdeps.c b/tool/build/mkdeps.c index b1b48b606..a27647aef 100644 --- a/tool/build/mkdeps.c +++ b/tool/build/mkdeps.c @@ -200,7 +200,7 @@ unsigned GetSourceId(const char *name, size_t len) { do { i = (hash + step * (step + 1) / 2) & (sources.n - 1); if (sources.p[i].hash == hash && - !timingsafe_bcmp(name, &strings.p[sources.p[i].name], len)) { + !memcmp(name, &strings.p[sources.p[i].name], len)) { return sources.p[i].id; } step++; @@ -437,8 +437,8 @@ void Explore(void) { int main(int argc, char *argv[]) { int i, fd; + char path[PATH_MAX]; if (argc == 2 && !strcmp(argv[1], "-n")) exit(0); - out = "/dev/stdout"; GetOpts(argc, argv); threads = GetCpuCount(); tls = calloc(threads, sizeof(*tls)); @@ -455,11 +455,14 @@ int main(int argc, char *argv[]) { LoadRelationships(argc, argv); Crunch(); Explore(); - CHECK_NE(-1, (fd = open(out, O_CREAT | O_WRONLY, 0644)), "open(%#s)", out); + ksnprintf(path, sizeof(path), "%s.%d", out, getpid()); + CHECK_NE(-1, (fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)), + "open(%#s)", path); for (i = 0; i < threads; ++i) { CHECK_NE(-1, xwrite(fd, bouts[i], appendz(bouts[i]).i)); } CHECK_NE(-1, close(fd)); + CHECK_NE(-1, rename(path, out)); for (i = 0; i < threads; ++i) { munmap(stack[i], GetStackSize()); free(bouts[i]); diff --git a/tool/build/runit.c b/tool/build/runit.c index c8b416361..6c26d9d15 100644 --- a/tool/build/runit.c +++ b/tool/build/runit.c @@ -20,41 +20,31 @@ #include "libc/bits/bits.h" #include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" -#include "libc/calls/struct/flock.h" -#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/stat.h" -#include "libc/dce.h" #include "libc/dns/dns.h" #include "libc/fmt/conv.h" -#include "libc/intrin/kprintf.h" #include "libc/limits.h" #include "libc/log/check.h" #include "libc/log/log.h" -#include "libc/macros.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/crc32.h" #include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/sock/ipclassify.internal.h" -#include "libc/sock/sock.h" #include "libc/stdio/stdio.h" +#include "libc/str/str.h" #include "libc/sysv/consts/af.h" #include "libc/sysv/consts/ex.h" -#include "libc/sysv/consts/f.h" -#include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/ipproto.h" #include "libc/sysv/consts/itimer.h" #include "libc/sysv/consts/limits.h" -#include "libc/sysv/consts/lock.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/prot.h" -#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sock.h" #include "libc/time/time.h" #include "libc/x/x.h" #include "net/https/https.h" -#include "third_party/mbedtls/net_sockets.h" #include "third_party/mbedtls/ssl.h" #include "third_party/zlib/zlib.h" #include "tool/build/lib/eztls.h" @@ -131,10 +121,6 @@ static void OnAlarm(int sig) { alarmed = true; } -forceinline pureconst size_t GreatestTwoDivisor(size_t x) { - return x & (~x + 1); -} - wontreturn void ShowUsage(FILE *f, int rc) { fprintf(f, "Usage: %s RUNITD PROGRAM HOSTNAME[:RUNITDPORT[:SSHPORT]]...\n", program_invocation_name); @@ -150,99 +136,6 @@ void CheckExists(const char *path) { } } -dontdiscard char *MakeDeployScript(struct addrinfo *remotenic, - size_t combytes) { - const char *ip4 = (const char *)&remotenic->ai_addr4->sin_addr; - return xasprintf("mkdir -p o/ && " - "dd bs=%zu count=%zu of=o/runitd.$$.com 2>/dev/null && " - "chmod +x o/runitd.$$.com && " - "o/runitd.$$.com -rdl%hhu.%hhu.%hhu.%hhu -p %hu && " - "rm -f o/runitd.$$.com", - GreatestTwoDivisor(combytes), - combytes ? combytes / GreatestTwoDivisor(combytes) : 0, - ip4[0], ip4[1], ip4[2], ip4[3], g_runitdport); -} - -void Upload(int pipe, int fd, struct stat *st) { - int64_t i; - for (i = 0; i < st->st_size;) { - CHECK_GT(splice(fd, &i, pipe, NULL, st->st_size - i, 0), 0); - } - CHECK_NE(-1, close(fd)); -} - -void DeployEphemeralRunItDaemonRemotelyViaSsh(struct addrinfo *ai) { - int lock; - size_t got; - char *args[7]; - struct stat st; - char linebuf[32]; - sigset_t chldmask, savemask; - int sshpid, wstatus, binfd, pipefds[2][2]; - struct sigaction ignore, saveint, savequit; - ignore.sa_flags = 0; - ignore.sa_handler = SIG_IGN; - sigemptyset(&ignore.sa_mask); - sigaction(SIGINT, &ignore, &saveint); - sigaction(SIGQUIT, &ignore, &savequit); - mkdir("o", 0755); - CHECK_NE(-1, (lock = open(gc(xasprintf("o/lock.%s", g_hostname)), - O_RDWR | O_CREAT, 0644))); - CHECK_NE(-1, fcntl(lock, F_SETLKW, &(struct flock){F_WRLCK})); - DEBUGF("ssh %s:%hu to spawn %s", g_hostname, g_runitdport, g_runitd); - CHECK_NE(-1, (binfd = open(g_runitd, O_RDONLY | O_CLOEXEC))); - CHECK_NE(-1, fstat(binfd, &st)); - args[0] = "ssh"; - args[1] = "-C"; - args[2] = "-p"; - args[3] = gc(xasprintf("%hu", g_sshport)); - args[4] = g_hostname; - args[5] = gc(MakeDeployScript(ai, st.st_size)); - args[6] = NULL; - sigemptyset(&chldmask); - sigaddset(&chldmask, SIGCHLD); - sigprocmask(SIG_BLOCK, &chldmask, &savemask); - CHECK_NE(-1, pipe2(pipefds[0], O_CLOEXEC)); - CHECK_NE(-1, pipe2(pipefds[1], O_CLOEXEC)); - CHECK_NE(-1, (sshpid = fork())); - if (!sshpid) { - sigaction(SIGINT, &(struct sigaction){0}, 0); - sigaction(SIGQUIT, &(struct sigaction){0}, 0); - sigprocmask(SIG_SETMASK, &savemask, 0); - dup2(pipefds[0][0], 0); - dup2(pipefds[1][1], 1); - execv(g_ssh, args); - _exit(127); - } - close(pipefds[0][0]); - close(pipefds[1][1]); - Upload(pipefds[0][1], binfd, &st); - LOGIFNEG1(close(pipefds[0][1])); - CHECK_NE(-1, (got = read(pipefds[1][0], linebuf, sizeof(linebuf)))); - CHECK_GT(got, 0, "on host %s", g_hostname); - linebuf[sizeof(linebuf) - 1] = '\0'; - if (strncmp(linebuf, "ready ", 6) != 0) { - FATALF("expected ready response but got %`'.*s", got, linebuf); - } else { - DEBUGF("got ready response"); - } - g_runitdport = (uint16_t)atoi(&linebuf[6]); - LOGIFNEG1(close(pipefds[1][0])); - CHECK_NE(-1, waitpid(sshpid, &wstatus, 0)); - LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL)); - if (WIFEXITED(wstatus)) { - DEBUGF("ssh %s exited with %d", g_hostname, WEXITSTATUS(wstatus)); - } else { - DEBUGF("ssh %s terminated with %s", g_hostname, - strsignal(WTERMSIG(wstatus))); - } - CHECK(WIFEXITED(wstatus) && !WEXITSTATUS(wstatus), "wstatus=%#x", wstatus); - LOGIFNEG1(fcntl(lock, F_SETLK, &(struct flock){F_UNLCK})); - sigaction(SIGINT, &saveint, 0); - sigaction(SIGQUIT, &savequit, 0); - close(lock); -} - void Connect(void) { const char *ip4; int rc, err, expo; @@ -267,7 +160,6 @@ void Connect(void) { expo = INITIAL_CONNECT_TIMEOUT; t1 = nowl(); LOGIFNEG1(sigaction(SIGALRM, &(struct sigaction){.sa_handler = OnAlarm}, 0)); -Reconnect: DEBUGF("connecting to %s (%hhu.%hhu.%hhu.%hhu) to run %s", g_hostname, ip4[0], ip4[1], ip4[2], ip4[3], g_prog); TryAgain: @@ -289,23 +181,8 @@ TryAgain: } goto TryAgain; } - if (err == ECONNREFUSED || err == EHOSTUNREACH || err == ECONNRESET) { - DEBUGF("got %s from %s (%hhu.%hhu.%hhu.%hhu)", strerror(err), g_hostname, - ip4[0], ip4[1], ip4[2], ip4[3]); - setitimer(ITIMER_REAL, &(const struct itimerval){0}, 0); - DeployEphemeralRunItDaemonRemotelyViaSsh(ai); - if (t2 > t1 + MAX_WAIT_CONNECT_SECONDS) { - FATALF("timeout connecting to %s (%hhu.%hhu.%hhu.%hhu:%d)", g_hostname, - ip4[0], ip4[1], ip4[2], ip4[3], ntohs(ai->ai_addr4->sin_port)); - unreachable; - } - usleep((expo *= 2)); - goto Reconnect; - } else { - FATALF("%s(%s:%hu): %s", "connect", g_hostname, g_runitdport, - strerror(err)); - unreachable; - } + FATALF("%s(%s:%hu): %s", "connect", g_hostname, g_runitdport, + strerror(err)); } else { DEBUGF("connected to %s", g_hostname); } diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 3203c00a8..1f6eb888d 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -6629,7 +6629,7 @@ static int HandleConnection(size_t i) { __isworker = true; connectionclose = false; if (!IsTiny() && systrace) { - __kbirth = rdtsc(); + kStartTsc = rdtsc(); } TRACE_BEGIN; if (sandboxed) {