Eliminate some flakes

- Get ASAN working on Windows.

- Deleting directories and then recreating them with the same name in a
  short period of time appears to be a no-no on Windows.

- There's no reason to call FlushFileBuffers on close() for pipes, and
  it's harmful since it might block indefinitely for no good reason.
This commit is contained in:
Justine Tunney 2021-02-03 06:22:51 -08:00
parent 27c899af56
commit 4e56d89dcd
60 changed files with 588 additions and 751 deletions

View file

@ -19,7 +19,7 @@
#include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h"
bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
int i;
for (i = 0; i < mm->i; ++i) {
if (mm->p[i].y < mm->p[i].x) return false;

View file

@ -17,38 +17,83 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/mem/alloca.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/nr.h"
static noasan size_t __assert_strlen(const char *s) {
size_t i = 0;
while (s[i]) ++i;
return i;
}
static noasan char *__assert_stpcpy(char *d, const char *s) {
size_t i;
for (i = 0;; ++i) {
if (!(d[i] = s[i])) {
return d + i;
}
}
}
static textsyscall noasan wontreturn void __assert_exit(int rc) {
if (!IsWindows()) {
asm volatile("syscall"
: /* no outputs */
: "a"(__NR_exit_group), "D"(rc)
: "memory");
unreachable;
} else {
ExitProcess(rc);
}
}
static textsyscall noasan ssize_t __assert_write(const void *data,
size_t size) {
ssize_t rc;
uint32_t wrote;
if (!IsWindows()) {
asm volatile("syscall"
: "=a"(rc)
: "0"(__NR_write), "D"(2), "S"(data), "d"(size)
: "rcx", "r11", "memory");
return rc;
} else {
if (WriteFile(GetStdHandle(kNtStdErrorHandle), data, size, &wrote, 0)) {
return wrote;
} else {
return -1;
}
}
}
/**
* Handles failure of assert() macro.
*/
relegated void __assert_fail(const char *expr, const char *file, int line) {
relegated wontreturn noasan void __assert_fail(const char *expr,
const char *file, int line) {
static bool once;
char *msg, *p, linebuf[16];
unsigned i, exprlen, filelen;
if (!once) {
once = true;
exprlen = expr ? strlen(expr) : 0;
filelen = file ? strlen(file) : 0;
if (cmpxchg(&once, false, true)) {
exprlen = expr ? __assert_strlen(expr) : 0;
filelen = file ? __assert_strlen(file) : 0;
p = msg = alloca(MIN(512, exprlen + filelen + 64));
p = mempcpy(p, file, filelen);
p = stpcpy(p, ":");
p = __assert_stpcpy(p, file);
p = __assert_stpcpy(p, ":");
if (line < 1) line = 1;
for (i = 0; line; line /= 10) linebuf[i++] = '0' + line % 10;
while (i) *p++ = linebuf[--i];
p = stpcpy(p, ":");
p = mempcpy(p, expr, exprlen);
p = stpcpy(p, "\r\n");
write(STDERR_FILENO, msg, p - msg);
p = __assert_stpcpy(p, ":");
p = __assert_stpcpy(p, expr);
p = __assert_stpcpy(p, "\r\n");
__assert_write(msg, p - msg);
if (weaken(__die)) weaken(__die)();
}
abort();
unreachable;
__assert_exit(23);
}

View file

@ -51,7 +51,7 @@ static struct CxaAtexitBlocks {
* @return 0 on success or nonzero w/ errno
* @note folks have forked libc in past just to unbloat atexit()
*/
int __cxa_atexit(void *fp, void *arg, void *pred) {
noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
unsigned i;
struct CxaAtexitBlock *b, *b2;
b = __cxa_blocks.p;
@ -83,7 +83,7 @@ int __cxa_atexit(void *fp, void *arg, void *pred) {
*
* @param pred can be null to match all
*/
void __cxa_finalize(void *pred) {
noasan void __cxa_finalize(void *pred) {
unsigned i;
unsigned long mask;
struct CxaAtexitBlock *b, *b2;

View file

@ -28,8 +28,8 @@
* bypassed by calling this function. However the caller is responsible
* for passing the magic memory handle on Windows NT to CloseHandle().
*/
struct DirectMap __mmap(void *addr, size_t size, unsigned prot, unsigned flags,
int fd, int64_t off) {
noasan struct DirectMap __mmap(void *addr, size_t size, unsigned prot,
unsigned flags, int fd, int64_t off) {
if (!IsWindows()) {
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
kNtInvalidHandleValue};

View file

@ -25,8 +25,9 @@
#include "libc/runtime/directmap.h"
#include "libc/sysv/consts/prot.h"
textwindows struct DirectMap __mmap$nt(void *addr, size_t size, unsigned prot,
int64_t handle, int64_t off) {
textwindows noasan struct DirectMap __mmap$nt(void *addr, size_t size,
unsigned prot, int64_t handle,
int64_t off) {
struct DirectMap dm;
if ((dm.maphandle = CreateFileMappingNuma(
handle, &kNtIsInheritable,

View file

@ -18,7 +18,7 @@
*/
#include "libc/runtime/memtrack.h"
unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
unsigned l, m, r;
l = 0;
r = mm->i;

View file

@ -46,7 +46,7 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
static textwindows char16_t *ParseInt(char16_t *p, int64_t *x) {
static textwindows noasan char16_t *ParseInt(char16_t *p, int64_t *x) {
*x = 0;
while (*p == ' ') p++;
while ('0' <= *p && *p <= '9') {
@ -56,8 +56,8 @@ static textwindows char16_t *ParseInt(char16_t *p, int64_t *x) {
return p;
}
static noinline textwindows void ForkIo(int64_t h, void *buf, size_t n,
bool32 (*f)()) {
static noinline textwindows noasan void ForkIo(int64_t h, void *buf, size_t n,
bool32 (*f)()) {
char *p;
size_t i;
uint32_t x;
@ -66,15 +66,17 @@ static noinline textwindows void ForkIo(int64_t h, void *buf, size_t n,
}
}
static noinline textwindows void WriteAll(int64_t h, void *buf, size_t n) {
static noinline textwindows noasan void WriteAll(int64_t h, void *buf,
size_t n) {
ForkIo(h, buf, n, WriteFile);
}
static noinline textwindows void ReadAll(int64_t h, void *buf, size_t n) {
static textwindows noinline noasan void ReadAll(int64_t h, void *buf,
size_t n) {
ForkIo(h, buf, n, ReadFile);
}
textwindows void WinMainForked(void) {
textwindows noasan void WinMainForked(void) {
void *addr;
jmp_buf jb;
uint64_t size;
@ -117,13 +119,13 @@ textwindows void WinMainForked(void) {
textwindows int fork$nt(void) {
jmp_buf jb;
int i, rc, pid;
char exe[PATH_MAX];
int64_t reader, writer;
int i, rc, pid, releaseme;
char *p, forkvar[6 + 21 + 1 + 21 + 1];
struct NtStartupInfo startinfo;
struct NtProcessInformation procinfo;
if ((pid = __getemptyfd()) == -1) return -1;
if ((pid = releaseme = __reservefd()) == -1) return -1;
if (!setjmp(jb)) {
if (CreatePipe(&reader, &writer, &kNtIsInheritable, 0)) {
p = stpcpy(forkvar, "_FORK=");
@ -148,6 +150,7 @@ textwindows int fork$nt(void) {
g_fds.p[pid].kind = kFdProcess;
g_fds.p[pid].handle = procinfo.hProcess;
g_fds.p[pid].flags = O_CLOEXEC;
releaseme = -1;
}
WriteAll(writer, jb, sizeof(jb));
WriteAll(writer, &_mmi.i, sizeof(_mmi.i));
@ -170,5 +173,8 @@ textwindows int fork$nt(void) {
} else {
rc = 0;
}
if (releaseme != -1) {
__releasefd(releaseme);
}
return rc;
}

View file

@ -32,7 +32,7 @@ struct DosArgv {
wint_t wc;
};
static textwindows wint_t DecodeDosArgv(const char16_t **s) {
static textwindows noasan wint_t DecodeDosArgv(const char16_t **s) {
wint_t x, y;
for (;;) {
if (!(x = *(*s)++)) break;
@ -50,7 +50,7 @@ static textwindows wint_t DecodeDosArgv(const char16_t **s) {
return x;
}
static textwindows void AppendDosArgv(struct DosArgv *st, wint_t wc) {
static textwindows noasan void AppendDosArgv(struct DosArgv *st, wint_t wc) {
uint64_t w;
w = tpenc(wc);
do {
@ -78,8 +78,8 @@ static textwindows void AppendDosArgv(struct DosArgv *st, wint_t wc) {
* @see libc/runtime/ntspawn.c
* @note kudos to Simon Tatham for figuring out quoting behavior
*/
textwindows int GetDosArgv(const char16_t *cmdline, char *buf, size_t size,
char **argv, size_t max) {
textwindows noasan int GetDosArgv(const char16_t *cmdline, char *buf,
size_t size, char **argv, size_t max) {
bool inquote;
size_t i, argc, slashes, quotes;
struct DosArgv st;

View file

@ -18,6 +18,30 @@
*/
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
static textwindows noasan axdx_t Recode16to8(char *dst, size_t dstsize,
const char16_t *src) {
axdx_t r;
uint64_t w;
wint_t x, y;
for (r.ax = 0, r.dx = 0;;) {
if (!(x = src[r.dx++])) break;
if (IsUtf16Cont(x)) continue;
if (!IsUcs2(x)) {
if (!(y = src[r.dx++])) break;
x = MergeUtf16(x, y);
}
for (w = tpenc(x); w && r.ax + 1 < dstsize; w >>= 8) {
dst[r.ax++] = w & 0xFF;
}
}
if (r.ax < dstsize) {
dst[r.ax] = 0;
}
return r;
}
/**
* Transcodes NT environment variable block from UTF-16 to UTF-8.
@ -29,8 +53,8 @@
* @param max is the pointer count capacity of envp
* @return number of variables decoded, excluding NULL-terminator
*/
textwindows int GetDosEnviron(const char16_t *env, char *buf, size_t size,
char **envp, size_t max) {
textwindows noasan int GetDosEnviron(const char16_t *env, char *buf,
size_t size, char **envp, size_t max) {
int i;
axdx_t r;
i = 0;
@ -38,7 +62,7 @@ textwindows int GetDosEnviron(const char16_t *env, char *buf, size_t size,
--size;
while (*env) {
if (i + 1 < max) envp[i++] = buf;
r = tprecode16to8(buf, size, env);
r = Recode16to8(buf, size, env);
size -= r.ax + 1;
buf += r.ax + 1;
env += r.dx;

View file

@ -24,7 +24,8 @@
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
static void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, int n) {
static noasan void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i,
int n) {
assert(i >= 0);
assert(i + n <= mm->i);
memcpy(mm->p + i, mm->p + i + n,
@ -32,7 +33,7 @@ static void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, int n) {
mm->i -= n;
}
static void CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
static noasan void CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
assert(i >= 0);
assert(i <= mm->i);
assert(mm->i < ARRAYLEN(mm->p));
@ -41,7 +42,7 @@ static void CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
++mm->i;
}
static int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
static noasan int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
if (mm->i == ARRAYLEN(mm->p)) return enomem();
CreateMemoryInterval(mm, i);
mm->p[i].y = x - 1;
@ -49,8 +50,8 @@ static int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
return 0;
}
int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
void wincb(struct MemoryIntervals *, int, int)) {
noasan int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
void wf(struct MemoryIntervals *, int, int)) {
unsigned l, r;
assert(y >= x);
assert(AreMemoryIntervalsOk(mm));
@ -81,16 +82,16 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
--r;
}
if (l <= r) {
if (IsWindows() && wincb) {
wincb(mm, l, r);
if (IsWindows() && wf) {
wf(mm, l, r);
}
RemoveMemoryIntervals(mm, l, r - l + 1);
}
return 0;
}
int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
int prot, int flags) {
noasan int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
int prot, int flags) {
unsigned i;
assert(y >= x);
assert(AreMemoryIntervalsOk(mm));

View file

@ -3,7 +3,6 @@
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/nt/enum/version.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/runtime.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -22,14 +22,14 @@
#include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h"
static void *GetFrameAddr(int f) {
static noasan void *GetFrameAddr(int f) {
intptr_t a;
a = f;
a *= FRAMESIZE;
return (void *)a;
}
void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) {
noasan void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) {
int i, ok;
for (i = l; i <= r; ++i) {
ok = UnmapViewOfFile(GetFrameAddr(mm->p[i].x));

View file

@ -35,7 +35,6 @@ static void __print$nt(const void *data, size_t len) {
savexmm(xmm + 128);
hand = __imp_GetStdHandle(kNtStdErrorHandle);
__imp_WriteFile(hand, data, len, &wrote, NULL);
__imp_FlushFileBuffers(hand);
loadxmm(xmm + 128);
}

View file

@ -72,6 +72,7 @@ void __print_string(const char *);
void __fast_math(void);
void *sbrk(intptr_t);
int brk(void *);
int NtGetVersion(void);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § runtime » optimizations

View file

@ -19,7 +19,6 @@
#include "libc/bits/pushpop.h"
#include "libc/nt/enum/version.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/internal.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/nr.h"
@ -29,7 +28,7 @@
/**
* Aborts program under enemy fire to avoid being taken alive.
*/
textsyscall void __stack_chk_fail(void) {
textsyscall noasan void __stack_chk_fail(void) {
size_t len;
const char *msg;
int64_t ax, cx, si;

View file

@ -35,7 +35,6 @@
#include "libc/nt/pedef.internal.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/directmap.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.h"
@ -56,16 +55,16 @@ struct WinArgs {
char envblock[ARG_MAX];
};
static textwindows void SetTrueColor(void) {
static noasan textwindows void SetTrueColor(void) {
SetEnvironmentVariable(u"TERM", u"xterm-truecolor");
}
static textwindows void MakeLongDoubleLongAgain(void) {
static noasan textwindows void MakeLongDoubleLongAgain(void) {
int x87cw = 0x037f; /* let's hope win32 won't undo this */
asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw));
}
static textwindows void NormalizeCmdExe(void) {
static noasan textwindows void NormalizeCmdExe(void) {
uint32_t mode;
int64_t handle, hstdin, hstdout, hstderr;
if ((int)weakaddr("v_ntsubsystem") == kNtImageSubsystemWindowsCui &&
@ -96,7 +95,7 @@ static textwindows void NormalizeCmdExe(void) {
}
}
static textwindows wontreturn void WinMainNew(void) {
static noasan textwindows wontreturn void WinMainNew(void) {
int64_t h;
size_t size;
int i, count;
@ -165,8 +164,8 @@ static textwindows wontreturn void WinMainNew(void) {
*
* @param hInstance call GetModuleHandle(NULL) from main if you need it
*/
textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
const char *lpCmdLine, int nCmdShow) {
noasan textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
const char *lpCmdLine, int nCmdShow) {
MakeLongDoubleLongAgain();
if (weaken(winsockinit)) weaken(winsockinit)();
if (weaken(WinMainForked)) weaken(WinMainForked)();