diff --git a/build/bootstrap/mkdeps.com b/build/bootstrap/mkdeps.com index e44772d33..f247a5756 100755 Binary files a/build/bootstrap/mkdeps.com and b/build/bootstrap/mkdeps.com differ 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) {