mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-07 03:38:31 +00:00
Elevate Windows production worthiness
- SQLite file locking now works on Windows - SQLite will now use fdatasync() on non-Apple platforms - Fix Ctrl-C handler on Windows to not crash with TLS - Signals now work in multithreaded apps on Windows - fcntl() will now accurately report EINVAL errors - fcntl() now has excellent --strace logging - Token bucket replenish now go 100x faster - *NSYNC cancellations now work on Windows - Support closefrom() on NetBSD
This commit is contained in:
parent
d38700687a
commit
997ce29ddc
95 changed files with 959 additions and 418 deletions
|
@ -250,7 +250,7 @@ TEST(pledge, stdio_fcntl_allowsSomeFirstArgs) {
|
|||
ASSERT_SYS(0, 3, fcntl(2, F_DUPFD_CLOEXEC, 3));
|
||||
ASSERT_SYS(0, 0, ioctl(0, FIOCLEX, 0));
|
||||
ASSERT_SYS(EPERM, 0, isatty(0));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, -1));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, 777));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, F_GETLK, &lk));
|
||||
ASSERT_SYS(EPERM, -1, fcntl(0, F_NOTIFY));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
|
|
32
test/libc/intrin/gettid_test.c
Normal file
32
test/libc/intrin/gettid_test.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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/calls/struct/sigaction.h"
|
||||
#include "libc/intrin/intrin.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
void OnSig(int sig) {
|
||||
kprintf("got sig\n");
|
||||
}
|
||||
|
||||
TEST(gettid, test) {
|
||||
signal(SIGTRAP, OnSig);
|
||||
DebugBreak();
|
||||
}
|
54
test/libc/thread/pthread_kill_test.c
Normal file
54
test/libc/thread/pthread_kill_test.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
int fds[2];
|
||||
_Thread_local sig_atomic_t gotsig;
|
||||
|
||||
void OnSig(int sig) {
|
||||
gotsig = 1;
|
||||
}
|
||||
|
||||
void *ReadWorker(void *arg) {
|
||||
char buf[8];
|
||||
ASSERT_SYS(EINTR, -1, read(fds[0], buf, 8));
|
||||
ASSERT_TRUE(gotsig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(pthread_kill, canCancelReadOperation) {
|
||||
pthread_t t;
|
||||
struct sigaction oldsa;
|
||||
struct sigaction sa = {.sa_handler = OnSig};
|
||||
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &sa, &oldsa));
|
||||
ASSERT_SYS(0, 0, pipe(fds));
|
||||
ASSERT_EQ(0, pthread_create(&t, 0, ReadWorker, 0));
|
||||
ASSERT_SYS(0, 0, usleep(100000)); // potentially flaky
|
||||
ASSERT_EQ(0, pthread_kill(t, SIGUSR1));
|
||||
ASSERT_EQ(0, pthread_join(t, 0));
|
||||
ASSERT_FALSE(gotsig);
|
||||
ASSERT_SYS(0, 0, close(fds[0]));
|
||||
ASSERT_SYS(0, 0, close(fds[1]));
|
||||
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &oldsa, 0));
|
||||
}
|
|
@ -21,7 +21,6 @@
|
|||
#include "libc/log/check.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
@ -147,6 +146,14 @@ TEST(ParseHttpMessage, testHttp09) {
|
|||
EXPECT_EQ(9, req->version);
|
||||
}
|
||||
|
||||
TEST(ParseHttpMessage, testTinyResponse) {
|
||||
static const char m[] = "HTTP/1.1 429 \r\n\r\n";
|
||||
InitHttpMessage(req, kHttpResponse);
|
||||
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
|
||||
EXPECT_EQ(429, req->status);
|
||||
EXPECT_STREQ("", gc(slice(m, req->message)));
|
||||
}
|
||||
|
||||
TEST(ParseHttpMessage, testLeadingLineFeeds_areIgnored) {
|
||||
static const char m[] = "\
|
||||
\r\n\
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
|
@ -47,27 +48,52 @@ void TearDown(void) {
|
|||
}
|
||||
|
||||
TEST(tokenbucket, test) {
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
ASSERT_EQ(2, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(2, AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_FALSE(AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_TRUE(AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
ASSERT_EQ(1, AcquireToken(tok.b, 0x7f000001, TB_CIDR));
|
||||
ASSERT_EQ(0, AcquireToken(tok.b, 0x7f000002, TB_CIDR));
|
||||
ASSERT_EQ(3, AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
for (int i = 0; i < 130; ++i) ReplenishTokens(tok.w, TB_WORDS);
|
||||
ASSERT_EQ(127, AcquireToken(tok.b, 0x08080808, TB_CIDR));
|
||||
}
|
||||
|
||||
void NaiveReplenishTokens(atomic_schar *b, size_t n) {
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
int x = atomic_load_explicit(b + i, memory_order_relaxed);
|
||||
if (x == 127) continue;
|
||||
atomic_fetch_add_explicit(b + i, 1, memory_order_acq_rel);
|
||||
}
|
||||
}
|
||||
|
||||
BENCH(tokenbucket, bench) {
|
||||
struct timespec t1, t2;
|
||||
|
||||
clock_gettime(0, &t1);
|
||||
NaiveReplenishTokens(tok.b, TB_BYTES);
|
||||
clock_gettime(0, &t2);
|
||||
kprintf("NaiveReplenishTokens took %'ld us\n",
|
||||
_timespec_tomicros(_timespec_sub(t2, t1)));
|
||||
|
||||
clock_gettime(0, &t1);
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
clock_gettime(0, &t2);
|
||||
kprintf("token bucket replenish took %'ld us\n",
|
||||
kprintf("ReplenishTokens empty took %'ld us\n",
|
||||
_timespec_tomicros(_timespec_sub(t2, t1)));
|
||||
|
||||
memset(tok.b, 127, TB_BYTES);
|
||||
clock_gettime(0, &t1);
|
||||
ReplenishTokens(tok.w, TB_WORDS);
|
||||
clock_gettime(0, &t2);
|
||||
kprintf("ReplenishTokens full took %'ld us\n",
|
||||
_timespec_tomicros(_timespec_sub(t2, t1)));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue