Make some more fixups

This commit is contained in:
Justine Tunney 2022-06-12 09:37:17 -07:00
parent 6070a53e89
commit 4ddfc47d6e
18 changed files with 81 additions and 259 deletions

Binary file not shown.

View file

@ -19,8 +19,6 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/strace.internal.h" #include "libc/calls/strace.internal.h"
#include "libc/intrin/pthread.h"
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h" #include "libc/nexgen32e/bsr.h"
@ -30,8 +28,6 @@
STATIC_YOINK("__cxa_finalize"); STATIC_YOINK("__cxa_finalize");
static pthread_mutex_t __cxa_lock;
/** /**
* Adds global destructor. * Adds global destructor.
* *
@ -51,7 +47,7 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
unsigned i; unsigned i;
struct CxaAtexitBlock *b, *b2; struct CxaAtexitBlock *b, *b2;
_Static_assert(ATEXIT_MAX == CHAR_BIT * sizeof(b->mask), ""); _Static_assert(ATEXIT_MAX == CHAR_BIT * sizeof(b->mask), "");
pthread_mutex_lock(&__cxa_lock); __cxa_lock();
b = __cxa_blocks.p; b = __cxa_blocks.p;
if (!b) b = __cxa_blocks.p = &__cxa_blocks.root; if (!b) b = __cxa_blocks.p = &__cxa_blocks.root;
if (!~b->mask) { if (!~b->mask) {
@ -60,7 +56,7 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
b2->next = b; b2->next = b;
__cxa_blocks.p = b = b2; __cxa_blocks.p = b = b2;
} else { } else {
pthread_mutex_unlock(&__cxa_lock); __cxa_unlock();
return enomem(); return enomem();
} }
} }
@ -70,6 +66,6 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
b->p[i].fp = fp; b->p[i].fp = fp;
b->p[i].arg = arg; b->p[i].arg = arg;
b->p[i].pred = pred; b->p[i].pred = pred;
pthread_mutex_unlock(&__cxa_lock); __cxa_unlock();
return 0; return 0;
} }

View file

@ -34,9 +34,12 @@
* @param pred can be null to match all * @param pred can be null to match all
*/ */
void __cxa_finalize(void *pred) { void __cxa_finalize(void *pred) {
void *fp, *arg;
unsigned i, mask; unsigned i, mask;
struct CxaAtexitBlock *b, *b2; struct CxaAtexitBlock *b, *b2;
StartOver: StartOver:
__cxa_lock();
StartOverLocked:
if ((b = __cxa_blocks.p)) { if ((b = __cxa_blocks.p)) {
for (;;) { for (;;) {
mask = b->mask; mask = b->mask;
@ -45,9 +48,11 @@ StartOver:
mask &= ~(1u << i); mask &= ~(1u << i);
if (!pred || pred == b->p[i].pred) { if (!pred || pred == b->p[i].pred) {
b->mask &= ~(1u << i); b->mask &= ~(1u << i);
if (b->p[i].fp) { if ((fp = b->p[i].fp)) {
STRACE("__cxa_finalize(%t, %p)", b->p[i].fp, b->p[i].arg); arg = b->p[i].arg;
((void (*)(void *))b->p[i].fp)(b->p[i].arg); __cxa_unlock();
STRACE("__cxa_finalize(%t, %p)", fp, arg);
((void (*)(void *))fp)(arg);
goto StartOver; goto StartOver;
} }
} }
@ -61,7 +66,7 @@ StartOver:
} }
} }
__cxa_blocks.p = b2; __cxa_blocks.p = b2;
goto StartOver; goto StartOverLocked;
} else { } else {
if (b->next) { if (b->next) {
b = b->next; b = b->next;
@ -71,4 +76,5 @@ StartOver:
} }
} }
} }
__cxa_unlock();
} }

21
libc/intrin/cxalock.c Normal file
View file

@ -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;

View file

@ -42,10 +42,6 @@ $(LIBC_INTRIN_A).pkg: \
$(LIBC_INTRIN_A_OBJS) \ $(LIBC_INTRIN_A_OBJS) \
$(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg) $(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: # we can't use asan and ubsan because:
# this is asan and ubsan # this is asan and ubsan
o/$(MODE)/libc/intrin/asan.o \ o/$(MODE)/libc/intrin/asan.o \
@ -76,20 +72,6 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: \
-fno-sanitize=all \ -fno-sanitize=all \
-fno-stack-protector -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/tls.greg.o \
o/$(MODE)/libc/intrin/exit.greg.o \ o/$(MODE)/libc/intrin/exit.greg.o \
o/$(MODE)/libc/intrin/exit1.greg.o \ o/$(MODE)/libc/intrin/exit1.greg.o \

View file

@ -55,36 +55,6 @@
extern hidden struct SymbolTable *__symtab; 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) { privileged static inline char *kadvance(char *p, char *e, long n) {
intptr_t t = (intptr_t)p; intptr_t t = (intptr_t)p;
if (__builtin_add_overflow(t, n, &t)) t = (intptr_t)e; 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, privileged static size_t kformat(char *b, size_t n, const char *fmt,
struct Timestamps ts) { va_list va) {
int si; int si;
wint_t t, u; wint_t t, u;
const char *abet; const char *abet;
@ -333,7 +303,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
continue; continue;
case 'T': case 'T':
x = ClocksToNanos(ts.start, ts.birth) % 86400000000000; x = ClocksToNanos(rdtsc(), kStartTsc) % 86400000000000;
goto FormatUnsigned; goto FormatUnsigned;
case 'P': 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, ...) { privileged size_t ksnprintf(char *b, size_t n, const char *fmt, ...) {
size_t m; size_t m;
va_list v; va_list v;
struct Timestamps t;
t = kenter();
va_start(v, fmt); va_start(v, fmt);
m = kformat(b, n, fmt, v, t); m = kformat(b, n, fmt, v);
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});
va_end(v); va_end(v);
return m; return m;
} }
@ -812,12 +753,7 @@ privileged size_t kusnprintf(char *b, size_t n, const char *fmt, ...) {
* @vforksafe * @vforksafe
*/ */
privileged size_t kvsnprintf(char *b, size_t n, const char *fmt, va_list v) { privileged size_t kvsnprintf(char *b, size_t n, const char *fmt, va_list v) {
size_t m; return kformat(b, n, fmt, v);
struct Timestamps t;
t = kenter();
m = kformat(b, n, fmt, v, t);
kleave(t);
return m;
} }
/** /**
@ -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) { privileged void kvprintf(const char *fmt, va_list v) {
size_t n; size_t n;
char b[4000]; char b[4000];
struct Timestamps t;
if (!v) return; if (!v) return;
t = kenter(); n = kformat(b, sizeof(b), fmt, v);
n = kformat(b, sizeof(b), fmt, v, t);
klog(b, MIN(n, sizeof(b) - 1)); klog(b, MIN(n, sizeof(b) - 1));
kleave(t);
} }
/** /**

View file

@ -3,11 +3,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
extern unsigned long long __kbirth;
void kprintf(const char *, ...); void kprintf(const char *, ...);
size_t ksnprintf(char *, size_t, const char *, ...); size_t ksnprintf(char *, size_t, const char *, ...);
size_t kusnprintf(char *, size_t, const char *, ...);
void kvprintf(const char *, va_list); void kvprintf(const char *, va_list);
size_t kvsnprintf(char *, size_t, const char *, va_list); size_t kvsnprintf(char *, size_t, const char *, va_list);
bool kisdangerous(const void *); bool kisdangerous(const void *);

View file

@ -26,7 +26,7 @@
/** /**
* Acquires mutex. * Acquires mutex.
*/ */
int pthread_mutex_lock(pthread_mutex_t *mutex) { noasan noubsan int pthread_mutex_lock(pthread_mutex_t *mutex) {
int me, owner; int me, owner;
unsigned tries; unsigned tries;
if (__threaded) { if (__threaded) {

View file

@ -27,7 +27,7 @@
/** /**
* Releases mutex. * Releases mutex.
*/ */
int pthread_mutex_unlock(pthread_mutex_t *mutex) { noasan noubsan int pthread_mutex_unlock(pthread_mutex_t *mutex) {
int owner; int owner;
bool shouldunlock; bool shouldunlock;
assert(mutex->reent > 0); assert(mutex->reent > 0);

View file

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_ #ifndef COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_
#define COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_ #define COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_
#include "libc/intrin/pthread.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
@ -16,10 +17,14 @@ struct CxaAtexitBlocks {
} * p, root; } * p, root;
}; };
extern pthread_mutex_t __cxa_lock_obj;
extern struct CxaAtexitBlocks __cxa_blocks; extern struct CxaAtexitBlocks __cxa_blocks;
void __cxa_printexits(FILE *, void *); 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_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_ */ #endif /* COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_ */

View file

@ -139,12 +139,11 @@ textwindows void WinMainForked(void) {
char *addr, *shad; char *addr, *shad;
struct DirectMap dm; struct DirectMap dm;
uint64_t size, upsize; uint64_t size, upsize;
int64_t oncrash, savetsc;
struct MemoryInterval *maps; struct MemoryInterval *maps;
char16_t fvar[21 + 1 + 21 + 1]; char16_t fvar[21 + 1 + 21 + 1];
int64_t oncrash, savetsc, savebir;
uint32_t i, varlen, oldprot, savepid; uint32_t i, varlen, oldprot, savepid;
long mapcount, mapcapacity, specialz; long mapcount, mapcapacity, specialz;
extern uint64_t ts asm("kStartTsc");
// check to see if the process was actually forked // check to see if the process was actually forked
// this variable should have the pipe handle numba // this variable should have the pipe handle numba
@ -198,13 +197,11 @@ textwindows void WinMainForked(void) {
// read the .data and .bss program image sections // read the .data and .bss program image sections
savepid = __pid; savepid = __pid;
savebir = __kbirth; savetsc = kStartTsc;
savetsc = ts;
ReadOrDie(reader, __data_start, __data_end - __data_start); ReadOrDie(reader, __data_start, __data_end - __data_start);
ReadOrDie(reader, __bss_start, __bss_end - __bss_start); ReadOrDie(reader, __bss_start, __bss_end - __bss_start);
__pid = savepid; __pid = savepid;
__kbirth = savebir; kStartTsc = savetsc;
ts = savetsc;
// apply fixups and reapply memory protections // apply fixups and reapply memory protections
_mmi.p = maps; _mmi.p = maps;

View file

@ -31,6 +31,7 @@ static inline bool IsMemtrackedImpl(int x, int y) {
} }
bool IsMemtracked(int x, int y) { bool IsMemtracked(int x, int y) {
/* assumes __mmi_lock() is held */
bool res; bool res;
res = IsMemtrackedImpl(x, y); res = IsMemtrackedImpl(x, y);
return res; return res;

View file

@ -20,7 +20,7 @@ extern _Atomic(int) __strace; /* SYS */
extern char *program_invocation_name; /* RII */ extern char *program_invocation_name; /* RII */
extern char *program_invocation_short_name; /* RII */ extern char *program_invocation_short_name; /* RII */
extern uint64_t __syscount; /* 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 kTmpPath[]; /* RII */
extern const char kNtSystemDirectory[]; /* RII */ extern const char kNtSystemDirectory[]; /* RII */
extern const char kNtWindowsDirectory[]; /* RII */ extern const char kNtWindowsDirectory[]; /* RII */

View file

@ -275,9 +275,8 @@ __msabi textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
const char *lpCmdLine, int64_t nCmdShow) { const char *lpCmdLine, int64_t nCmdShow) {
const char16_t *cmdline; const char16_t *cmdline;
extern char os asm("__hostos"); extern char os asm("__hostos");
extern uint64_t ts asm("kStartTsc");
os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */ os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
ts = rdtsc(); kStartTsc = rdtsc();
__pid = GetCurrentProcessId(); __pid = GetCurrentProcessId();
#if !IsTiny() #if !IsTiny()
__wincrashearly = AddVectoredExceptionHandler(1, (void *)OnEarlyWinCrash); __wincrashearly = AddVectoredExceptionHandler(1, (void *)OnEarlyWinCrash);

View file

@ -384,28 +384,33 @@ BENCH(printf, bench) {
char b[128]; char b[128];
int snprintf_(char *, size_t, const char *, ...) asm("snprintf"); int snprintf_(char *, size_t, const char *, ...) asm("snprintf");
EZBENCH2("ksnprintf fmt", donothing, ksnprintf(b, 128, ".")); EZBENCH2("ksnprintf fmt", donothing, ksnprintf(b, 128, "."));
EZBENCH2("kusnprintf fmt", donothing, kusnprintf(b, 128, "."));
EZBENCH2("snprintf fmt", donothing, snprintf_(b, 128, ".")); EZBENCH2("snprintf fmt", donothing, snprintf_(b, 128, "."));
EZBENCH2("kusnprintf str", donothing, EZBENCH2("ksnprintf str", donothing,
kusnprintf(b, 128, "%s\n", "hello world")); ksnprintf(b, 128, "%s\n", "hello world"));
EZBENCH2("snprintf str", donothing, EZBENCH2("snprintf str", donothing,
snprintf_(b, 128, "%s\n", "hello world")); snprintf_(b, 128, "%s\n", "hello world"));
EZBENCH2("kusnprintf utf8", donothing, EZBENCH2("ksnprintf utf8", donothing,
kusnprintf(b, 128, "%s\n", "天地玄黄宇宙洪荒天地玄黄宇宙洪荒")); ksnprintf(b, 128, "%s\n", "天地玄黄宇宙洪荒天地玄黄宇宙洪荒"));
EZBENCH2("snprintf utf8", donothing, EZBENCH2("snprintf utf8", donothing,
snprintf_(b, 128, "%s\n", "天地玄黄宇宙洪荒天地玄黄宇宙洪荒")); snprintf_(b, 128, "%s\n", "天地玄黄宇宙洪荒天地玄黄宇宙洪荒"));
EZBENCH2("kusnprintf chinese", donothing, EZBENCH2("ksnprintf chinese", donothing,
kusnprintf(b, 128, "%hs\n", u"天地玄黄宇宙洪荒")); ksnprintf(b, 128, "%hs\n", u"天地玄黄宇宙洪荒"));
EZBENCH2("snprintf chinese", donothing, EZBENCH2("snprintf chinese", donothing,
snprintf_(b, 128, "%hs\n", u"天地玄黄宇宙洪荒")); snprintf_(b, 128, "%hs\n", u"天地玄黄宇宙洪荒"));
EZBENCH2("kusnprintf astral", donothing, EZBENCH2("ksnprintf astral", donothing,
kusnprintf(b, 128, "%hs\n", u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷")); ksnprintf(b, 128, "%hs\n", u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷"));
EZBENCH2("snprintf astral", donothing, EZBENCH2("snprintf astral", donothing,
snprintf_(b, 128, "%hs\n", u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷")); snprintf_(b, 128, "%hs\n", u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷"));
EZBENCH2("kusnprintf octal", donothing, EZBENCH2("ksnprintf octal", donothing, ksnprintf(b, 128, "%#lo", ULONG_MAX));
kusnprintf(b, 128, "%#lo", ULONG_MAX)); EZBENCH2("snprintf octal", donothing, snprintf(b, 128, "%#lo", ULONG_MAX));
EZBENCH2("kusnprintf long", donothing, kusnprintf(b, 128, "%ld", LONG_MAX)); EZBENCH2("ksnprintf long", donothing, ksnprintf(b, 128, "%ld", LONG_MAX));
EZBENCH2("snprintf long", donothing, snprintf_(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("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"));
} }

View file

@ -200,7 +200,7 @@ unsigned GetSourceId(const char *name, size_t len) {
do { do {
i = (hash + step * (step + 1) / 2) & (sources.n - 1); i = (hash + step * (step + 1) / 2) & (sources.n - 1);
if (sources.p[i].hash == hash && 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; return sources.p[i].id;
} }
step++; step++;
@ -437,8 +437,8 @@ void Explore(void) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int i, fd; int i, fd;
char path[PATH_MAX];
if (argc == 2 && !strcmp(argv[1], "-n")) exit(0); if (argc == 2 && !strcmp(argv[1], "-n")) exit(0);
out = "/dev/stdout";
GetOpts(argc, argv); GetOpts(argc, argv);
threads = GetCpuCount(); threads = GetCpuCount();
tls = calloc(threads, sizeof(*tls)); tls = calloc(threads, sizeof(*tls));
@ -455,11 +455,14 @@ int main(int argc, char *argv[]) {
LoadRelationships(argc, argv); LoadRelationships(argc, argv);
Crunch(); Crunch();
Explore(); 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) { for (i = 0; i < threads; ++i) {
CHECK_NE(-1, xwrite(fd, bouts[i], appendz(bouts[i]).i)); CHECK_NE(-1, xwrite(fd, bouts[i], appendz(bouts[i]).i));
} }
CHECK_NE(-1, close(fd)); CHECK_NE(-1, close(fd));
CHECK_NE(-1, rename(path, out));
for (i = 0; i < threads; ++i) { for (i = 0; i < threads; ++i) {
munmap(stack[i], GetStackSize()); munmap(stack[i], GetStackSize());
free(bouts[i]); free(bouts[i]);

View file

@ -20,41 +20,31 @@
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h" #include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.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/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/dns/dns.h" #include "libc/dns/dns.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/log/check.h" #include "libc/log/check.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/nexgen32e/crc32.h" #include "libc/nexgen32e/crc32.h"
#include "libc/runtime/gc.internal.h" #include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sock/ipclassify.internal.h" #include "libc/sock/ipclassify.internal.h"
#include "libc/sock/sock.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h" #include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ex.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/ipproto.h"
#include "libc/sysv/consts/itimer.h" #include "libc/sysv/consts/itimer.h"
#include "libc/sysv/consts/limits.h" #include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/lock.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/sock.h" #include "libc/sysv/consts/sock.h"
#include "libc/time/time.h" #include "libc/time/time.h"
#include "libc/x/x.h" #include "libc/x/x.h"
#include "net/https/https.h" #include "net/https/https.h"
#include "third_party/mbedtls/net_sockets.h"
#include "third_party/mbedtls/ssl.h" #include "third_party/mbedtls/ssl.h"
#include "third_party/zlib/zlib.h" #include "third_party/zlib/zlib.h"
#include "tool/build/lib/eztls.h" #include "tool/build/lib/eztls.h"
@ -131,10 +121,6 @@ static void OnAlarm(int sig) {
alarmed = true; alarmed = true;
} }
forceinline pureconst size_t GreatestTwoDivisor(size_t x) {
return x & (~x + 1);
}
wontreturn void ShowUsage(FILE *f, int rc) { wontreturn void ShowUsage(FILE *f, int rc) {
fprintf(f, "Usage: %s RUNITD PROGRAM HOSTNAME[:RUNITDPORT[:SSHPORT]]...\n", fprintf(f, "Usage: %s RUNITD PROGRAM HOSTNAME[:RUNITDPORT[:SSHPORT]]...\n",
program_invocation_name); 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) { void Connect(void) {
const char *ip4; const char *ip4;
int rc, err, expo; int rc, err, expo;
@ -267,7 +160,6 @@ void Connect(void) {
expo = INITIAL_CONNECT_TIMEOUT; expo = INITIAL_CONNECT_TIMEOUT;
t1 = nowl(); t1 = nowl();
LOGIFNEG1(sigaction(SIGALRM, &(struct sigaction){.sa_handler = OnAlarm}, 0)); 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], DEBUGF("connecting to %s (%hhu.%hhu.%hhu.%hhu) to run %s", g_hostname, ip4[0],
ip4[1], ip4[2], ip4[3], g_prog); ip4[1], ip4[2], ip4[3], g_prog);
TryAgain: TryAgain:
@ -289,23 +181,8 @@ TryAgain:
} }
goto 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, FATALF("%s(%s:%hu): %s", "connect", g_hostname, g_runitdport,
strerror(err)); strerror(err));
unreachable;
}
} else { } else {
DEBUGF("connected to %s", g_hostname); DEBUGF("connected to %s", g_hostname);
} }

View file

@ -6629,7 +6629,7 @@ static int HandleConnection(size_t i) {
__isworker = true; __isworker = true;
connectionclose = false; connectionclose = false;
if (!IsTiny() && systrace) { if (!IsTiny() && systrace) {
__kbirth = rdtsc(); kStartTsc = rdtsc();
} }
TRACE_BEGIN; TRACE_BEGIN;
if (sandboxed) { if (sandboxed) {