mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Make improvements
- Polyfill pselect() on Windows - Add -O NOFILE flag to pledge.com - Polyfill ppoll() on NetBSD, XNU, and Windows - Support negative numbers and errno in sizetol() - Add .RSS, .NOFILE, and .MAXCORE to Landlock Make - Fix issue with .PLEDGE preventing touching of output files - Add __watch() function (like ftrace) for logging memory changes
This commit is contained in:
parent
d3b599a796
commit
f0701d2a24
35 changed files with 635 additions and 340 deletions
|
@ -23,7 +23,7 @@
|
|||
# - tool/build/runitd.c
|
||||
|
||||
.PRECIOUS: o/$(MODE)/%.com.ok
|
||||
o/$(MODE)/%.com.ok: .PLEDGE = stdio rpath wpath cpath proc inet
|
||||
o/$(MODE)/%.com.ok: .PLEDGE = stdio rpath wpath cpath proc fattr inet
|
||||
o/$(MODE)/%.com.ok: \
|
||||
o/$(MODE)/tool/build/runit.com \
|
||||
o/$(MODE)/tool/build/runitd.com \
|
||||
|
|
|
@ -35,7 +35,7 @@ static void SetLimit(int resource, uint64_t soft, uint64_t hard) {
|
|||
if (setrlimit(resource, &lim) == -1) {
|
||||
if (!getrlimit(resource, &old)) {
|
||||
lim.rlim_max = MIN(hard, old.rlim_max);
|
||||
lim.rlim_cur = MIN(soft, lim.rlim_max);
|
||||
lim.rlim_cur = MIN(soft, old.rlim_max);
|
||||
if (!setrlimit(resource, &lim)) {
|
||||
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
|
||||
DescribeRlimitName(resource), lim.rlim_cur, lim.rlim_max);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/itimer.h"
|
||||
#include "libc/time/time.h"
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -36,8 +36,8 @@
|
|||
*/
|
||||
int getttysize(int fd, struct winsize *out) {
|
||||
if (__nocolor) {
|
||||
out->ws_col = strtoimax(firstnonnull(getenv("COLUMNS"), "80"), NULL, 0);
|
||||
out->ws_row = strtoimax(firstnonnull(getenv("ROWS"), "40"), NULL, 0);
|
||||
out->ws_col = atoi(firstnonnull(getenv("COLUMNS"), "80"));
|
||||
out->ws_row = atoi(firstnonnull(getenv("ROWS"), "40"));
|
||||
out->ws_xpixel = 0;
|
||||
out->ws_ypixel = 0;
|
||||
return 0;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/sock/struct/pollfd.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
@ -51,9 +52,11 @@
|
|||
* on both sockets and files at the same time. We also poll for signals
|
||||
* while poll is polling.
|
||||
*/
|
||||
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint64_t *ms) {
|
||||
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint64_t *ms,
|
||||
const sigset_t *sigmask) {
|
||||
bool ok;
|
||||
uint32_t avail;
|
||||
sigset_t oldmask;
|
||||
struct sys_pollfd_nt pipefds[8];
|
||||
struct sys_pollfd_nt sockfds[64];
|
||||
int pipeindices[ARRAYLEN(pipefds)];
|
||||
|
@ -61,6 +64,7 @@ textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint64_t *ms) {
|
|||
int i, sn, pn, failed, gotinvals, gotpipes, gotsocks, waitfor;
|
||||
|
||||
// check for interrupts early before doing work
|
||||
if (sigmask && __sig_mask(SIG_SETMASK, sigmask, &oldmask)) return -1;
|
||||
if (_check_interrupts(false, g_fds.p)) return eintr();
|
||||
|
||||
// do the planning
|
||||
|
|
|
@ -81,7 +81,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
|||
}
|
||||
} else {
|
||||
millis = timeout_ms;
|
||||
rc = sys_poll_nt(fds, nfds, &millis);
|
||||
rc = sys_poll_nt(fds, nfds, &millis, 0);
|
||||
}
|
||||
|
||||
#if defined(SYSDEBUG) && _POLLTRACE
|
||||
|
|
107
libc/calls/ppoll.c
Normal file
107
libc/calls/ppoll.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*-*- 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/strace.internal.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sock/ppoll.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/sock/struct/pollfd.internal.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Waits for something to happen on multiple file descriptors at once.
|
||||
*
|
||||
* This function is the same as saying:
|
||||
*
|
||||
* sigset_t old;
|
||||
* sigprocmask(SIG_SETMASK, sigmask, &old);
|
||||
* poll(fds, nfds, timeout);
|
||||
* sigprocmask(SIG_SETMASK, old, 0);
|
||||
*
|
||||
* Except it'll happen atomically if the kernel supports doing that. On
|
||||
* kernel such as XNU and NetBSD which don't, this wrapper falls back to
|
||||
* doing the thing described above.
|
||||
*
|
||||
* @param timeout if null will block indefinitely
|
||||
* @param sigmask may be null in which case no mask change happens
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
* @norestart
|
||||
*/
|
||||
int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
|
||||
const sigset_t *sigmask) {
|
||||
int e, i, rc;
|
||||
uint64_t millis;
|
||||
sigset_t oldmask;
|
||||
|
||||
if (IsAsan() && (!__asan_is_valid(fds, nfds * sizeof(struct pollfd)) ||
|
||||
(timeout && !__asan_is_valid(timeout, sizeof(timeout))) ||
|
||||
(sigmask && !__asan_is_valid(sigmask, sizeof(sigmask))))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
rc = sys_ppoll(fds, nfds, timeout, sigmask);
|
||||
if (rc == -1 && errno == ENOSYS) {
|
||||
errno = e;
|
||||
if (!timeout ||
|
||||
__builtin_add_overflow(timeout->tv_sec, timeout->tv_nsec / 1000000,
|
||||
&millis)) {
|
||||
millis = -1;
|
||||
}
|
||||
if (sigmask) sys_sigprocmask(SIG_SETMASK, sigmask, &oldmask);
|
||||
rc = poll(fds, nfds, millis);
|
||||
if (sigmask) sys_sigprocmask(SIG_SETMASK, &oldmask, 0);
|
||||
}
|
||||
} else {
|
||||
if (!timeout || __builtin_add_overflow(
|
||||
timeout->tv_sec, timeout->tv_nsec / 1000000, &millis)) {
|
||||
millis = -1;
|
||||
}
|
||||
rc = sys_poll_nt(fds, nfds, &millis, sigmask);
|
||||
}
|
||||
|
||||
#if defined(SYSDEBUG) && _POLLTRACE
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
kprintf(STRACE_PROLOGUE "ppoll(");
|
||||
if ((!IsAsan() && kisdangerous(fds)) ||
|
||||
(IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd)))) {
|
||||
kprintf("%p", fds);
|
||||
} else {
|
||||
kprintf("[{");
|
||||
for (i = 0; i < MIN(5, nfds); ++i) {
|
||||
kprintf("%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
|
||||
DescribePollFlags(fds[i].events),
|
||||
DescribePollFlags(fds[i].revents));
|
||||
}
|
||||
kprintf("%s}]", i == 5 ? "..." : "");
|
||||
}
|
||||
kprintf(", %'zu, %s, %s) → %d% lm\n", nfds, DescribeTimeval(0, timeout),
|
||||
DescribeSigset(0, sigmask), rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int GetExponent(int c) {
|
||||
switch (c) {
|
||||
|
@ -65,27 +66,41 @@ static int GetExponent(int c) {
|
|||
* characters after it (e.g. kbit, Mibit, TiB) are ignored. Spaces
|
||||
* before the integer are ignored, and overflows will be detected.
|
||||
*
|
||||
* Negative numbers are permissible, as well as a leading `+` sign. To
|
||||
* tell the difference between an error return and `-1` you must clear
|
||||
* `errno` before calling and test whether it changed.
|
||||
*
|
||||
* @param s is non-null nul-terminated input string
|
||||
* @param b is multiplier which should be 1000 or 1024
|
||||
* @return size greater than or equal 0 or -1 on error
|
||||
* @error EINVAL if error is due to bad syntax
|
||||
* @error EOVERFLOW if error is due to overflow
|
||||
*/
|
||||
long sizetol(const char *s, long b) {
|
||||
long x;
|
||||
int c, e;
|
||||
int c, e, d;
|
||||
do {
|
||||
c = *s++;
|
||||
} while (c == ' ' || c == '\t');
|
||||
if (!isdigit(c)) return -1;
|
||||
d = c == '-' ? -1 : 1;
|
||||
if (c == '-' || c == '+') c = *s++;
|
||||
if (!isdigit(c)) {
|
||||
return einval();
|
||||
}
|
||||
x = 0;
|
||||
do {
|
||||
if (__builtin_mul_overflow(x, 10, &x) ||
|
||||
__builtin_add_overflow(x, c - '0', &x)) {
|
||||
return -1;
|
||||
__builtin_add_overflow(x, (c - '0') * d, &x)) {
|
||||
return eoverflow();
|
||||
}
|
||||
} while (isdigit((c = *s++)));
|
||||
if ((e = GetExponent(c)) == -1) return -1;
|
||||
if ((e = GetExponent(c)) == -1) {
|
||||
return einval();
|
||||
}
|
||||
while (e--) {
|
||||
if (__builtin_mul_overflow(x, b, &x)) return -1;
|
||||
if (__builtin_mul_overflow(x, b, &x)) {
|
||||
return eoverflow();
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/enum/lang.h"
|
||||
|
|
|
@ -36,6 +36,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
extern FILE *__log_file;
|
||||
|
||||
int __watch(void *, size_t);
|
||||
void __die(void) relegated wontreturn; /* print backtrace and abort() */
|
||||
void meminfo(int); /* shows malloc statistics &c. */
|
||||
void memsummary(int); /* light version of same thing */
|
||||
|
|
|
@ -65,6 +65,10 @@ o/$(MODE)/libc/log/checkfail.o: private \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-mgeneral-regs-only
|
||||
|
||||
o/$(MODE)/libc/log/watch.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-ffreestanding
|
||||
|
||||
o/$(MODE)/libc/log/attachdebugger.o \
|
||||
o/$(MODE)/libc/log/checkaligned.o \
|
||||
o/$(MODE)/libc/log/checkfail.o \
|
||||
|
|
65
libc/log/watch-hook.S
Normal file
65
libc/log/watch-hook.S
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 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/macros.internal.h"
|
||||
|
||||
__watch_hook:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
and $-16,%rsp
|
||||
sub $0x80,%rsp
|
||||
movaps %xmm0,0x00(%rsp)
|
||||
movaps %xmm1,0x10(%rsp)
|
||||
movaps %xmm2,0x20(%rsp)
|
||||
movaps %xmm3,0x30(%rsp)
|
||||
movaps %xmm4,0x40(%rsp)
|
||||
movaps %xmm5,0x50(%rsp)
|
||||
movaps %xmm6,0x60(%rsp)
|
||||
movaps %xmm7,0x70(%rsp)
|
||||
push %rax
|
||||
push %rax
|
||||
push %rdi
|
||||
push %rsi
|
||||
push %rdx
|
||||
push %rcx
|
||||
push %r8
|
||||
push %r9
|
||||
push %r10
|
||||
push %r11
|
||||
call __watcher
|
||||
pop %r11
|
||||
pop %r10
|
||||
pop %r9
|
||||
pop %r8
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
pop %rax
|
||||
pop %rax
|
||||
movaps 0x00(%rsp),%xmm0
|
||||
movaps 0x10(%rsp),%xmm1
|
||||
movaps 0x20(%rsp),%xmm2
|
||||
movaps 0x30(%rsp),%xmm3
|
||||
movaps 0x40(%rsp),%xmm4
|
||||
movaps 0x50(%rsp),%xmm5
|
||||
movaps 0x60(%rsp),%xmm6
|
||||
movaps 0x70(%rsp),%xmm7
|
||||
leave
|
||||
ret
|
||||
.endfn __watch_hook,globl
|
87
libc/log/watch.c
Normal file
87
libc/log/watch.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*-*- 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/intrin/bits.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static bool __watch_busy;
|
||||
static void *__watch_addr;
|
||||
static size_t __watch_size;
|
||||
static char __watch_last[4096];
|
||||
|
||||
void __watch_hook(void);
|
||||
|
||||
static noinstrument inline void Copy(char *p, char *q, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
p[i] = q[i];
|
||||
}
|
||||
}
|
||||
|
||||
static noinstrument inline int Cmp(char *p, char *q, size_t n) {
|
||||
int c;
|
||||
if (n == 8) return READ64LE(p) != READ64LE(q);
|
||||
if (n == 4) return READ32LE(p) != READ32LE(q);
|
||||
for (; n; ++p, ++q, --n) {
|
||||
if (*p != *q) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
noinstrument void __watcher(void) {
|
||||
if (__watch_busy) return;
|
||||
__watch_busy = true;
|
||||
if (Cmp(__watch_last, __watch_addr, __watch_size)) {
|
||||
kprintf("watchpoint %p changed:\n"
|
||||
"%#.*hhs\n"
|
||||
"%#.*hhs\n",
|
||||
__watch_addr, //
|
||||
__watch_size, __watch_last, //
|
||||
__watch_size, __watch_addr);
|
||||
Copy(__watch_last, __watch_addr, __watch_size);
|
||||
ShowBacktrace(2, __builtin_frame_address(0));
|
||||
}
|
||||
__watch_busy = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches memory address for changes.
|
||||
*
|
||||
* It's useful for situations when ASAN and GDB both aren't working.
|
||||
*/
|
||||
int __watch(void *addr, size_t size) {
|
||||
static bool once;
|
||||
if (__watch_busy) ebusy();
|
||||
if (size > sizeof(__watch_last)) return einval();
|
||||
if (!once) {
|
||||
if (!GetSymbolTable()) return -1;
|
||||
if (__hook(__watch_hook, GetSymbolTable()) == -1) return -1;
|
||||
once = true;
|
||||
}
|
||||
__watch_addr = addr;
|
||||
__watch_size = size;
|
||||
Copy(__watch_last, __watch_addr, __watch_size);
|
||||
return 0;
|
||||
}
|
|
@ -111,10 +111,6 @@ o//libc/runtime/opensymboltable.greg.o: private \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
o/$(MODE)/libc/runtime/ftrace.greg.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-mgeneral-regs-only
|
||||
|
||||
LIBC_RUNTIME_LIBS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)))
|
||||
LIBC_RUNTIME_SRCS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_RUNTIME_HDRS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_HDRS))
|
||||
|
|
|
@ -87,7 +87,8 @@ int sys_socketpair_nt_stream(int, int, int, int[2]) hidden;
|
|||
int sys_socketpair_nt_dgram(int, int, int, int[2]) hidden;
|
||||
*/
|
||||
int sys_socketpair_nt(int, int, int, int[2]) hidden;
|
||||
int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *) hidden;
|
||||
int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *,
|
||||
const sigset_t *) hidden;
|
||||
|
||||
size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *,
|
||||
size_t) hidden;
|
||||
|
|
|
@ -18,9 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/select.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Does what poll() does except with bitset API.
|
||||
|
@ -32,9 +36,30 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
const struct timespec *timeout, const sigset_t *sigmask) {
|
||||
int rc;
|
||||
sigset_t oldmask;
|
||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
||||
POLLTRACE("pselect(%d, %p, %p, %p, [%s], %s) → %d% m", nfds, readfds,
|
||||
writefds, exceptfds, DescribeTimeval(rc, timeout),
|
||||
DescribeSigset(0, sigmask), rc);
|
||||
struct timeval tv, *tvp;
|
||||
if (nfds < 0) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() &&
|
||||
((readfds && !__asan_is_valid(readfds, FD_SIZE(nfds))) ||
|
||||
(writefds && !__asan_is_valid(writefds, FD_SIZE(nfds))) ||
|
||||
(exceptfds && !__asan_is_valid(exceptfds, FD_SIZE(nfds))) ||
|
||||
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))) ||
|
||||
(sigmask && !__asan_is_valid(sigmask, sizeof(*sigmask))))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
||||
} else {
|
||||
if (timeout) {
|
||||
tv.tv_sec = timeout->tv_sec;
|
||||
tv.tv_usec = timeout->tv_nsec / 1000;
|
||||
tvp = &tv;
|
||||
} else {
|
||||
tvp = 0;
|
||||
}
|
||||
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, tvp, sigmask);
|
||||
}
|
||||
POLLTRACE("pselect(%d, %p, %p, %p, %s, %s) → %d% m", nfds, readfds, writefds,
|
||||
exceptfds, DescribeTimeval(0, timeout), DescribeSigset(0, sigmask),
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sock/select.h"
|
||||
|
@ -27,14 +28,12 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
fd_set *exceptfds, struct timeval *timeout) {
|
||||
fd_set *exceptfds, struct timeval *timeout,
|
||||
const sigset_t *sigmask) {
|
||||
uint64_t millis;
|
||||
int i, pfds, events, fdcount;
|
||||
struct pollfd fds[64];
|
||||
|
||||
// check for interrupts early before doing work
|
||||
if (_check_interrupts(false, g_fds.p)) return eintr();
|
||||
|
||||
// convert bitsets to pollfd
|
||||
for (pfds = i = 0; i < nfds; ++i) {
|
||||
events = 0;
|
||||
|
@ -60,7 +59,7 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
|
|||
}
|
||||
|
||||
// call our nt poll implementation
|
||||
fdcount = sys_poll_nt(fds, pfds, &millis);
|
||||
fdcount = sys_poll_nt(fds, pfds, &millis, sigmask);
|
||||
if (fdcount == -1) return -1;
|
||||
|
||||
// convert pollfd back to bitsets
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/select.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Does what poll() does except with bitset API.
|
||||
|
@ -35,10 +37,18 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
int rc;
|
||||
POLLTRACE("select(%d, %p, %p, %p, %s) → ...", nfds, readfds, writefds,
|
||||
exceptfds, DescribeTimeval(0, timeout));
|
||||
if (!IsWindows()) {
|
||||
if (nfds < 0) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() &&
|
||||
((readfds && !__asan_is_valid(readfds, FD_SIZE(nfds))) ||
|
||||
(writefds && !__asan_is_valid(writefds, FD_SIZE(nfds))) ||
|
||||
(exceptfds && !__asan_is_valid(exceptfds, FD_SIZE(nfds))) ||
|
||||
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
} else {
|
||||
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, timeout);
|
||||
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, timeout, 0);
|
||||
}
|
||||
POLLTRACE("select(%d, %p, %p, %p, [%s]) → %d% m", nfds, readfds, writefds,
|
||||
exceptfds, DescribeTimeval(rc, timeout), rc);
|
||||
|
|
|
@ -11,13 +11,14 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
typedef struct fd_set {
|
||||
uint64_t fds_bits[FD_SETSIZE / 64];
|
||||
unsigned long fds_bits[FD_SETSIZE / (sizeof(long) * CHAR_BIT)];
|
||||
} fd_set;
|
||||
|
||||
#define FD_ISSET(FD, SET) (((SET)->fds_bits[(FD) >> 6] >> ((FD)&63)) & 1)
|
||||
#define FD_SET(FD, SET) ((SET)->fds_bits[(FD) >> 6] |= 1ull << ((FD)&63))
|
||||
#define FD_CLR(FD, SET) ((SET)->fds_bits[(FD) >> 6] &= ~(1ull << ((FD)&63)))
|
||||
#define FD_ZERO(SET) bzero((SET)->fds_bits, sizeof((SET)->fds_bits))
|
||||
#define FD_SIZE(bits) (((bits) + (sizeof(long) * CHAR_BIT) - 1) / sizeof(long))
|
||||
|
||||
int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
||||
int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_INTERNAL_H_
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int32_t sys_poll(struct pollfd *, uint64_t, signed) hidden;
|
||||
int sys_ppoll(struct pollfd *, size_t, const struct timespec *,
|
||||
const sigset_t *);
|
||||
int sys_poll_metal(struct pollfd *, size_t, unsigned);
|
||||
int sys_poll_nt(struct pollfd *, uint64_t, uint64_t *) hidden;
|
||||
int sys_poll_nt(struct pollfd *, uint64_t, uint64_t *, const sigset_t *) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -105,7 +105,7 @@ static void EmptySignalMask(void) {
|
|||
}
|
||||
|
||||
static void FixIrregularFds(void) {
|
||||
int i, fd, maxfds;
|
||||
int e, i, fd, maxfds;
|
||||
struct rlimit rlim;
|
||||
struct pollfd *pfds;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
|
@ -118,6 +118,9 @@ static void FixIrregularFds(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
e = errno;
|
||||
if (!closefrom(3)) return;
|
||||
errno = e;
|
||||
if (IsWindows()) {
|
||||
maxfds = 64;
|
||||
} else {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
|
@ -24,7 +25,10 @@ TEST(sizetol, test) {
|
|||
EXPECT_EQ(0, sizetol("0", 1000));
|
||||
EXPECT_EQ(0, sizetol("0kb", 1000));
|
||||
EXPECT_EQ(31337, sizetol("31337", 1000));
|
||||
EXPECT_EQ(+123, sizetol("+123", 1000));
|
||||
EXPECT_EQ(-123, sizetol("-123", 1000));
|
||||
EXPECT_EQ(1000, sizetol("1kb", 1000));
|
||||
EXPECT_EQ(-1000, sizetol("-1kb", 1000));
|
||||
EXPECT_EQ(2000, sizetol("2k", 1000));
|
||||
EXPECT_EQ(1024, sizetol("1kb", 1024));
|
||||
EXPECT_EQ(2048, sizetol("2k", 1024));
|
||||
|
@ -43,11 +47,13 @@ TEST(sizetol, test) {
|
|||
EXPECT_EQ(100, sizetol("\t100\t", 1024));
|
||||
}
|
||||
|
||||
TEST(sizetol, testNegative_notAllowed) {
|
||||
EXPECT_EQ(-1, sizetol("-23", 1000));
|
||||
}
|
||||
|
||||
TEST(sizetol, testOverflow_isDetected) {
|
||||
EXPECT_EQ(9000000000000000000, sizetol("9eb", 1000));
|
||||
EXPECT_EQ(-1, sizetol("10eb", 1000));
|
||||
EXPECT_SYS(EOVERFLOW, -1, sizetol("10eb", 1000));
|
||||
}
|
||||
|
||||
TEST(sizetol, badSyntax) {
|
||||
EXPECT_SYS(EINVAL, -1, sizetol("- 1", 1000));
|
||||
EXPECT_SYS(EINVAL, -1, sizetol("- 1", 1000));
|
||||
EXPECT_SYS(EOVERFLOW, -1, sizetol("10eb", 1000));
|
||||
}
|
||||
|
|
|
@ -56,17 +56,17 @@ o/$(MODE)/test/libc/sock/%.com.dbg: \
|
|||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/test/libc/sock/unix_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc unix
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc unix
|
||||
|
||||
o/$(MODE)/test/libc/sock/setsockopt_test.com.runs \
|
||||
o/$(MODE)/test/libc/sock/sendfile_test.com.runs \
|
||||
o/$(MODE)/test/libc/sock/poll_test.com.runs \
|
||||
o/$(MODE)/test/libc/sock/pollfd_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc inet
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||
|
||||
o/$(MODE)/test/libc/sock/sendrecvmsg_test.com.runs \
|
||||
o/$(MODE)/test/libc/sock/nointernet_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc inet recvfd sendfd
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet recvfd sendfd
|
||||
|
||||
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
||||
|
||||
|
|
|
@ -71,10 +71,10 @@ o/$(MODE)/test/tool/net/%.com.dbg: \
|
|||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/test/tool/net/redbean_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc inet
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||
|
||||
o/$(MODE)/test/tool/net/sqlite_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc flock
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
|
||||
.PHONY: o/$(MODE)/test/tool/net
|
||||
o/$(MODE)/test/tool/net: \
|
||||
|
|
3
third_party/make/README.cosmo
vendored
3
third_party/make/README.cosmo
vendored
|
@ -22,8 +22,11 @@ LOCAL CHANGES
|
|||
- .UNSANDBOXED variable to disable pledge / unveil
|
||||
- .CPU variable which tunes CPU rlimit in seconds
|
||||
- .MEMORY variable for virtual memory limit, e.g. 512m
|
||||
- .RSS variable for resident memory limit, e.g. 512m
|
||||
- .FSIZE variable which tunes max file size, e.g. 1g
|
||||
- .NPROC variable which tunes fork() / clone() limit
|
||||
- .NOFILE variable which tunes file descriptor limit
|
||||
- .MAXCORE variable to set upper limit on core dumps
|
||||
- Do automatic setup and teardown of TMPDIR per rule
|
||||
- Remove code that forces slow path if not using /bin/sh
|
||||
- Remove 200,000 lines of VAX/OS2/DOS/AMIGA/etc. code
|
||||
|
|
126
third_party/make/config.h
vendored
126
third_party/make/config.h
vendored
|
@ -2,116 +2,6 @@
|
|||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/* CPU and C ABI indicator */
|
||||
#ifndef __i386__
|
||||
/* #undef __i386__ */
|
||||
#endif
|
||||
#ifndef __x86_64_x32__
|
||||
/* #undef __x86_64_x32__ */
|
||||
#endif
|
||||
#ifndef __x86_64__
|
||||
#define __x86_64__ 1
|
||||
#endif
|
||||
#ifndef __alpha__
|
||||
/* #undef __alpha__ */
|
||||
#endif
|
||||
#ifndef __arm__
|
||||
/* #undef __arm__ */
|
||||
#endif
|
||||
#ifndef __armhf__
|
||||
/* #undef __armhf__ */
|
||||
#endif
|
||||
#ifndef __arm64_ilp32__
|
||||
/* #undef __arm64_ilp32__ */
|
||||
#endif
|
||||
#ifndef __arm64__
|
||||
/* #undef __arm64__ */
|
||||
#endif
|
||||
#ifndef __hppa__
|
||||
/* #undef __hppa__ */
|
||||
#endif
|
||||
#ifndef __hppa64__
|
||||
/* #undef __hppa64__ */
|
||||
#endif
|
||||
#ifndef __ia64_ilp32__
|
||||
/* #undef __ia64_ilp32__ */
|
||||
#endif
|
||||
#ifndef __ia64__
|
||||
/* #undef __ia64__ */
|
||||
#endif
|
||||
#ifndef __m68k__
|
||||
/* #undef __m68k__ */
|
||||
#endif
|
||||
#ifndef __mips__
|
||||
/* #undef __mips__ */
|
||||
#endif
|
||||
#ifndef __mipsn32__
|
||||
/* #undef __mipsn32__ */
|
||||
#endif
|
||||
#ifndef __mips64__
|
||||
/* #undef __mips64__ */
|
||||
#endif
|
||||
#ifndef __powerpc__
|
||||
/* #undef __powerpc__ */
|
||||
#endif
|
||||
#ifndef __powerpc64__
|
||||
/* #undef __powerpc64__ */
|
||||
#endif
|
||||
#ifndef __powerpc64_elfv2__
|
||||
/* #undef __powerpc64_elfv2__ */
|
||||
#endif
|
||||
#ifndef __riscv32__
|
||||
/* #undef __riscv32__ */
|
||||
#endif
|
||||
#ifndef __riscv64__
|
||||
/* #undef __riscv64__ */
|
||||
#endif
|
||||
#ifndef __riscv32_ilp32__
|
||||
/* #undef __riscv32_ilp32__ */
|
||||
#endif
|
||||
#ifndef __riscv32_ilp32f__
|
||||
/* #undef __riscv32_ilp32f__ */
|
||||
#endif
|
||||
#ifndef __riscv32_ilp32d__
|
||||
/* #undef __riscv32_ilp32d__ */
|
||||
#endif
|
||||
#ifndef __riscv64_ilp32__
|
||||
/* #undef __riscv64_ilp32__ */
|
||||
#endif
|
||||
#ifndef __riscv64_ilp32f__
|
||||
/* #undef __riscv64_ilp32f__ */
|
||||
#endif
|
||||
#ifndef __riscv64_ilp32d__
|
||||
/* #undef __riscv64_ilp32d__ */
|
||||
#endif
|
||||
#ifndef __riscv64_lp64__
|
||||
/* #undef __riscv64_lp64__ */
|
||||
#endif
|
||||
#ifndef __riscv64_lp64f__
|
||||
/* #undef __riscv64_lp64f__ */
|
||||
#endif
|
||||
#ifndef __riscv64_lp64d__
|
||||
/* #undef __riscv64_lp64d__ */
|
||||
#endif
|
||||
#ifndef __s390__
|
||||
/* #undef __s390__ */
|
||||
#endif
|
||||
#ifndef __s390x__
|
||||
/* #undef __s390x__ */
|
||||
#endif
|
||||
#ifndef __sh__
|
||||
/* #undef __sh__ */
|
||||
#endif
|
||||
#ifndef __sparc__
|
||||
/* #undef __sparc__ */
|
||||
#endif
|
||||
#ifndef __sparc64__
|
||||
/* #undef __sparc64__ */
|
||||
#endif
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
||||
|
||||
/* Define to the number of bits in type 'ptrdiff_t'. */
|
||||
#define BITSIZEOF_PTRDIFF_T 64
|
||||
|
||||
|
@ -401,7 +291,7 @@
|
|||
#define HAVE_POSIX_SPAWNATTR_SETSIGMASK 1
|
||||
|
||||
/* Define to 1 if you have the `pselect' function. */
|
||||
/* #undef HAVE_PSELECT */
|
||||
#define HAVE_PSELECT 1
|
||||
|
||||
/* Define to 1 if you have the `pstat_getdynamic' function. */
|
||||
/* #undef HAVE_PSTAT_GETDYNAMIC */
|
||||
|
@ -425,7 +315,7 @@
|
|||
#define HAVE_SETEUID 1
|
||||
|
||||
/* Define to 1 if you have the `setlinebuf' function. */
|
||||
/* #undef HAVE_SETLINEBUF */
|
||||
#define HAVE_SETLINEBUF 1
|
||||
|
||||
/* Define to 1 if you have the `setregid' function. */
|
||||
#define HAVE_SETREGID 1
|
||||
|
@ -451,12 +341,6 @@
|
|||
/* Define to 1 if 'wint_t' is a signed integer type. */
|
||||
/* #undef HAVE_SIGNED_WINT_T */
|
||||
|
||||
/* Define to 1 if you have the `sigsetmask' function. */
|
||||
/* #undef HAVE_SIGSETMASK */
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
/* #undef HAVE_SOCKET */
|
||||
|
||||
/* Define to 1 if you have the <spawn.h> header file. */
|
||||
#define HAVE_SPAWN_H 1
|
||||
|
||||
|
@ -623,7 +507,11 @@
|
|||
#define MAKE_HOST "x86_64-cosmopolitan"
|
||||
|
||||
/* Define to 1 to enable job server support in GNU make. */
|
||||
/* TODO(jart): make it work */
|
||||
/*
|
||||
* TODO(jart): Why does job server not work? We don't need it, since the
|
||||
* last thing we'd ever want is a recursive make, however it
|
||||
* would be nice to confirm it's not a bug in our libc impl.
|
||||
*/
|
||||
/* #define MAKE_JOBSERVER 1 */
|
||||
|
||||
/* Define to 1 to enable symbolic link timestamp checking. */
|
||||
|
|
221
third_party/make/job.c
vendored
221
third_party/make/job.c
vendored
|
@ -55,6 +55,8 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/pr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/libcxx/math.h"
|
||||
|
@ -416,7 +418,7 @@ get_target_variable (const char *name,
|
|||
const char *
|
||||
get_tmpdir (struct file *file)
|
||||
{
|
||||
return get_target_variable (STRING_SIZE_TUPLE("TMPDIR"), file, 0);
|
||||
return get_target_variable (STRING_SIZE_TUPLE ("TMPDIR"), file, 0);
|
||||
}
|
||||
|
||||
char *
|
||||
|
@ -1798,61 +1800,28 @@ get_base_cpu_freq_mhz (void)
|
|||
return KCPUIDS(16H, EAX) & 0x7fff;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
set_limit (int r, long lo, long hi)
|
||||
{
|
||||
struct rlimit old;
|
||||
struct rlimit lim = {lo, hi};
|
||||
if (!setrlimit (r, &lim))
|
||||
return 0;
|
||||
if (getrlimit (r, &old))
|
||||
return -1;
|
||||
lim.rlim_cur = MIN (lim.rlim_cur, old.rlim_max);
|
||||
lim.rlim_max = MIN (lim.rlim_max, old.rlim_max);
|
||||
return setrlimit (r, &lim);
|
||||
}
|
||||
|
||||
int
|
||||
set_cpu_limit (int secs)
|
||||
{
|
||||
int mhz, lim;
|
||||
struct rlimit rlim;
|
||||
if (secs <= 0) return;
|
||||
if (IsWindows()) return;
|
||||
if (!(mhz = get_base_cpu_freq_mhz())) return;
|
||||
if (secs <= 0) return 0;
|
||||
if (!(mhz = get_base_cpu_freq_mhz())) return eopnotsupp();
|
||||
lim = ceil(3100. / mhz * secs);
|
||||
rlim.rlim_cur = lim;
|
||||
rlim.rlim_max = lim + 1;
|
||||
if (setrlimit(RLIMIT_CPU, &rlim) == -1)
|
||||
{
|
||||
if (getrlimit(RLIMIT_CPU, &rlim) == -1)
|
||||
return;
|
||||
if (lim < rlim.rlim_cur)
|
||||
{
|
||||
rlim.rlim_cur = lim;
|
||||
setrlimit(RLIMIT_CPU, &rlim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_fsz_limit (long n)
|
||||
{
|
||||
struct rlimit rlim;
|
||||
if (n <= 0) return;
|
||||
if (IsWindows()) return;
|
||||
rlim.rlim_cur = n;
|
||||
rlim.rlim_max = n << 1;
|
||||
if (setrlimit(RLIMIT_FSIZE, &rlim) == -1)
|
||||
{
|
||||
if (getrlimit(RLIMIT_FSIZE, &rlim) == -1)
|
||||
return;
|
||||
rlim.rlim_cur = n;
|
||||
setrlimit(RLIMIT_FSIZE, &rlim);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_mem_limit (long n)
|
||||
{
|
||||
struct rlimit rlim = {n, n};
|
||||
if (n <= 0) return;
|
||||
if (IsWindows() || IsXnu()) return;
|
||||
setrlimit(RLIMIT_AS, &rlim);
|
||||
}
|
||||
|
||||
void
|
||||
set_pro_limit (long n)
|
||||
{
|
||||
struct rlimit rlim = {n, n};
|
||||
if (n <= 0) return;
|
||||
setrlimit(RLIMIT_NPROC, &rlim);
|
||||
return set_limit (RLIMIT_CPU, lim, lim + 1);
|
||||
}
|
||||
|
||||
static struct sysinfo g_sysinfo;
|
||||
|
@ -1920,18 +1889,18 @@ child_execute_job (struct childbase *child,
|
|||
}
|
||||
|
||||
internet = parse_bool (get_target_variable
|
||||
(STRING_SIZE_TUPLE(".INTERNET"),
|
||||
(STRING_SIZE_TUPLE (".INTERNET"),
|
||||
c ? c->file : 0, "0"));
|
||||
|
||||
unsandboxed = parse_bool (get_target_variable
|
||||
(STRING_SIZE_TUPLE(".UNSANDBOXED"),
|
||||
(STRING_SIZE_TUPLE (".UNSANDBOXED"),
|
||||
c ? c->file : 0, "0"));
|
||||
|
||||
if (c)
|
||||
{
|
||||
sandboxed = !unsandboxed;
|
||||
strict = parse_bool (get_target_variable
|
||||
(STRING_SIZE_TUPLE(".STRICT"),
|
||||
(STRING_SIZE_TUPLE (".STRICT"),
|
||||
c->file, "0"));
|
||||
}
|
||||
else
|
||||
|
@ -1943,7 +1912,7 @@ child_execute_job (struct childbase *child,
|
|||
if (!unsandboxed)
|
||||
{
|
||||
promises = emptytonull (get_target_variable
|
||||
(STRING_SIZE_TUPLE(".PLEDGE"),
|
||||
(STRING_SIZE_TUPLE (".PLEDGE"),
|
||||
c ? c->file : 0, 0));
|
||||
if (promises)
|
||||
promises = xstrdup (promises);
|
||||
|
@ -1968,52 +1937,158 @@ child_execute_job (struct childbase *child,
|
|||
internet ? " with internet access" : ""));
|
||||
|
||||
/* [jart] Set cpu seconds quota. */
|
||||
if ((s = get_target_variable (STRING_SIZE_TUPLE(".CPU"),
|
||||
if (RLIMIT_CPU < RLIM_NLIMITS &&
|
||||
(s = get_target_variable (STRING_SIZE_TUPLE (".CPU"),
|
||||
c ? c->file : 0, 0)))
|
||||
{
|
||||
int secs;
|
||||
secs = atoi (s);
|
||||
DB (DB_JOBS, (_("Setting cpu limit of %d seconds\n"), secs));
|
||||
set_cpu_limit (secs);
|
||||
if (!set_cpu_limit (secs))
|
||||
DB (DB_JOBS, (_("Set cpu limit of %d seconds\n"), secs));
|
||||
else
|
||||
DB (DB_JOBS, (_("Failed to set CPU limit: %s\n"), strerror (errno)));
|
||||
}
|
||||
|
||||
/* [jart] Set virtual memory quota. */
|
||||
if ((s = get_target_variable (STRING_SIZE_TUPLE(".MEMORY"),
|
||||
if (RLIMIT_AS < RLIM_NLIMITS &&
|
||||
(s = get_target_variable (STRING_SIZE_TUPLE (".MEMORY"),
|
||||
c ? c->file : 0, 0)))
|
||||
{
|
||||
long bytes;
|
||||
char buf[16];
|
||||
errno = 0;
|
||||
if (!strchr (s, '%'))
|
||||
bytes = sizetol (s, 1024);
|
||||
else
|
||||
bytes = strtod (s, 0) / 100. * g_sysinfo.totalram;
|
||||
DB (DB_JOBS, (_("Setting virtual memory limit of %s\n"),
|
||||
(FormatMemorySize (buf, bytes, 1024), buf)));
|
||||
set_mem_limit (bytes);
|
||||
if (bytes > 0)
|
||||
{
|
||||
if (!set_limit (RLIMIT_AS, bytes, bytes))
|
||||
DB (DB_JOBS, (_("Set virtual memory limit of %s\n"),
|
||||
(FormatMemorySize (buf, bytes, 1024), buf)));
|
||||
else
|
||||
DB (DB_JOBS, (_("Failed to set virtual memory: %s\n"),
|
||||
strerror (errno)));
|
||||
}
|
||||
else if (errno)
|
||||
{
|
||||
OSS (error, NILF, "%s: .MEMORY invalid: %s",
|
||||
argv[0], strerror (errno));
|
||||
_Exit (127);
|
||||
}
|
||||
}
|
||||
|
||||
/* [jart] Set file size limit. */
|
||||
if ((s = get_target_variable (STRING_SIZE_TUPLE(".FSIZE"),
|
||||
/* [jart] Set resident memory quota. */
|
||||
if (RLIMIT_RSS < RLIM_NLIMITS &&
|
||||
(s = get_target_variable (STRING_SIZE_TUPLE (".RSS"),
|
||||
c ? c->file : 0, 0)))
|
||||
{
|
||||
long bytes;
|
||||
char buf[16];
|
||||
bytes = sizetol (s, 1000);
|
||||
DB (DB_JOBS, (_("Setting file size limit of %s\n"),
|
||||
(FormatMemorySize (buf, bytes, 1000), buf)));
|
||||
set_fsz_limit (bytes);
|
||||
errno = 0;
|
||||
if (!strchr (s, '%'))
|
||||
bytes = sizetol (s, 1024);
|
||||
else
|
||||
bytes = strtod (s, 0) / 100. * g_sysinfo.totalram;
|
||||
if (bytes > 0)
|
||||
{
|
||||
if (!set_limit (RLIMIT_RSS, bytes, bytes))
|
||||
DB (DB_JOBS, (_("Set resident memory limit of %s\n"),
|
||||
(FormatMemorySize (buf, bytes, 1024), buf)));
|
||||
else
|
||||
DB (DB_JOBS, (_("Failed to set resident memory: %s\n"),
|
||||
strerror (errno)));
|
||||
}
|
||||
else if (errno)
|
||||
{
|
||||
OSS (error, NILF, "%s: .RSS invalid: %s",
|
||||
argv[0], strerror (errno));
|
||||
_Exit (127);
|
||||
}
|
||||
}
|
||||
|
||||
/* [jart] Set file size limit. */
|
||||
if (RLIMIT_FSIZE < RLIM_NLIMITS &&
|
||||
(s = get_target_variable (STRING_SIZE_TUPLE (".FSIZE"),
|
||||
c ? c->file : 0, 0)))
|
||||
{
|
||||
long bytes;
|
||||
char buf[16];
|
||||
errno = 0;
|
||||
if ((bytes = sizetol (s, 1000)) > 0)
|
||||
{
|
||||
if (!set_limit (RLIMIT_FSIZE, bytes, bytes * 1.5))
|
||||
DB (DB_JOBS, (_("Set file size limit of %s\n"),
|
||||
(FormatMemorySize (buf, bytes, 1000), buf)));
|
||||
else
|
||||
DB (DB_JOBS, (_("Failed to set file size limit: %s\n"),
|
||||
strerror (errno)));
|
||||
}
|
||||
else if (errno)
|
||||
{
|
||||
OSS (error, NILF, "%s: .FSIZE invalid: %s",
|
||||
argv[0], strerror (errno));
|
||||
_Exit (127);
|
||||
}
|
||||
}
|
||||
|
||||
/* [jart] Set core dump limit. */
|
||||
if (RLIMIT_CORE < RLIM_NLIMITS &&
|
||||
(s = get_target_variable (STRING_SIZE_TUPLE (".MAXCORE"),
|
||||
c ? c->file : 0, 0)))
|
||||
{
|
||||
long bytes;
|
||||
char buf[16];
|
||||
errno = 0;
|
||||
if ((bytes = sizetol (s, 1000)) > 0)
|
||||
{
|
||||
if (!set_limit (RLIMIT_CORE, bytes, bytes))
|
||||
DB (DB_JOBS, (_("Set core dump limit of %s\n"),
|
||||
(FormatMemorySize (buf, bytes, 1000), buf)));
|
||||
else
|
||||
DB (DB_JOBS, (_("Failed to set core dump limit: %s\n"),
|
||||
strerror (errno)));
|
||||
}
|
||||
else if (errno)
|
||||
{
|
||||
OSS (error, NILF, "%s: .MAXCORE invalid: %s",
|
||||
argv[0], strerror (errno));
|
||||
_Exit (127);
|
||||
}
|
||||
}
|
||||
|
||||
/* [jart] Set process limit. */
|
||||
if ((s = get_target_variable (STRING_SIZE_TUPLE(".NPROC"),
|
||||
if (RLIMIT_NPROC < RLIM_NLIMITS &&
|
||||
(s = get_target_variable (STRING_SIZE_TUPLE (".NPROC"),
|
||||
c ? c->file : 0, 0)))
|
||||
{
|
||||
int procs;
|
||||
if ((procs = atoi (s)) > 0)
|
||||
{
|
||||
DB (DB_JOBS, (_("Setting process limit to %d + %d preexisting\n"),
|
||||
procs, g_sysinfo.procs));
|
||||
set_pro_limit (procs + g_sysinfo.procs);
|
||||
if (!set_limit (RLIMIT_NPROC,
|
||||
procs + g_sysinfo.procs,
|
||||
procs + g_sysinfo.procs))
|
||||
DB (DB_JOBS, (_("Set process limit to %d + %d preexisting\n"),
|
||||
procs, g_sysinfo.procs));
|
||||
else
|
||||
DB (DB_JOBS, (_("Failed to set process limit: %s\n"),
|
||||
strerror (errno)));
|
||||
}
|
||||
}
|
||||
|
||||
/* [jart] Set file descriptor limit. */
|
||||
if (RLIMIT_NOFILE < RLIM_NLIMITS &&
|
||||
(s = get_target_variable (STRING_SIZE_TUPLE (".NOFILE"),
|
||||
c ? c->file : 0, 0)))
|
||||
{
|
||||
int fds;
|
||||
if ((fds = atoi (s)) > 0)
|
||||
{
|
||||
if (!set_limit (RLIMIT_NOFILE, fds, fds))
|
||||
DB (DB_JOBS, (_("Set file descriptor limit to %d\n"), fds));
|
||||
else
|
||||
DB (DB_JOBS, (_("Failed to set process limit: %s\n"),
|
||||
strerror (errno)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1
third_party/make/make.mk
vendored
1
third_party/make/make.mk
vendored
|
@ -119,6 +119,7 @@ THIRD_PARTY_MAKE_DIRECTDEPS = \
|
|||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_SOCK \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TIME \
|
||||
|
|
5
third_party/make/makeint.inc
vendored
5
third_party/make/makeint.inc
vendored
|
@ -14,7 +14,6 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/makedev.h"
|
||||
|
@ -31,11 +30,13 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -46,11 +47,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/utime.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
#include "third_party/musl/glob.h"
|
||||
|
|
16
third_party/make/posixos.c
vendored
16
third_party/make/posixos.c
vendored
|
@ -16,7 +16,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
#include "third_party/make/makeint.inc"
|
||||
/**/
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "third_party/make/config.h"
|
||||
#include "third_party/make/debug.h"
|
||||
#include "third_party/make/job.h"
|
||||
#include "third_party/make/os.h"
|
||||
|
@ -293,11 +297,6 @@ static RETSIGTYPE job_noop(int sig UNUSED) {
|
|||
static void set_child_handler_action_flags(int set_handler, int set_alarm) {
|
||||
struct sigaction sa;
|
||||
|
||||
#ifdef __EMX__
|
||||
/* The child handler must be turned off here. */
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
#endif
|
||||
|
||||
memset(&sa, '\0', sizeof sa);
|
||||
sa.sa_handler = child_handler;
|
||||
sa.sa_flags = set_handler ? 0 : SA_RESTART;
|
||||
|
@ -391,11 +390,8 @@ int get_bad_stdin(void) {
|
|||
/* Set file descriptors to be inherited / not inherited by subprocesses. */
|
||||
|
||||
#if !defined(F_SETFD) || !defined(F_GETFD)
|
||||
void fd_inherit(int fd) {
|
||||
}
|
||||
void fd_noinherit(int fd) {
|
||||
}
|
||||
|
||||
void fd_inherit(int fd) {}
|
||||
void fd_noinherit(int fd) {}
|
||||
#else
|
||||
|
||||
#ifndef FD_CLOEXEC
|
||||
|
|
8
third_party/python/python.mk
vendored
8
third_party/python/python.mk
vendored
|
@ -2097,13 +2097,13 @@ o/$(MODE)/third_party/python/Lib/test/test_wsgiref.py.runs: private \
|
|||
/usr/local/etc/mime.types
|
||||
|
||||
o/$(MODE)/third_party/python/Lib/test/test_epoll.py.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc inet
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||
o/$(MODE)/third_party/python/Lib/test/test_fcntl.py.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc flock
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
o/$(MODE)/third_party/python/Lib/test/test_signal.py.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc flock inet
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock inet
|
||||
o/$(MODE)/third_party/python/Lib/test/test_timeout.py.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath proc inet
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||
|
||||
o/$(MODE)/third_party/python/Lib/test/test_grammar.py.runs: \
|
||||
o/$(MODE)/third_party/python/pythontester.com
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/copyfile.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
|
@ -32,12 +29,15 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/io.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/kcpuids.h"
|
||||
|
@ -505,7 +505,7 @@ void SetFszLimit(long n) {
|
|||
if (n <= 0) return;
|
||||
if (IsWindows()) return;
|
||||
rlim.rlim_cur = n;
|
||||
rlim.rlim_max = n << 1;
|
||||
rlim.rlim_max = n + (n >> 1);
|
||||
if (setrlimit(RLIMIT_FSIZE, &rlim) == -1) {
|
||||
if (getrlimit(RLIMIT_FSIZE, &rlim) == -1) return;
|
||||
rlim.rlim_cur = n;
|
||||
|
@ -1191,7 +1191,10 @@ int main(int argc, char *argv[]) {
|
|||
if (!(exitcode = WEXITSTATUS(ws)) || exitcode == 254) {
|
||||
if (touchtarget && target) {
|
||||
makedirs(xdirname(target), 0755);
|
||||
touch(target, 0644);
|
||||
if (touch(target, 0644)) {
|
||||
exitcode = 90;
|
||||
appends(&output, "\nfailed to touch output file\n");
|
||||
}
|
||||
}
|
||||
if (movepath) {
|
||||
if (!MovePreservingDestinationInode(tmpout, movepath)) {
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/landlock.h"
|
||||
#include "libc/calls/pledge.h"
|
||||
|
@ -34,8 +32,10 @@
|
|||
#include "libc/elf/struct/ehdr.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/io.h"
|
||||
|
@ -56,6 +56,7 @@
|
|||
#include "libc/sysv/consts/pr.h"
|
||||
#include "libc/sysv/consts/prio.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/rlim.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/consts/sched.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -86,7 +87,8 @@ usage: pledge.com [-hnN] PROG ARGS...\n\
|
|||
-N don't normalize file descriptors\n\
|
||||
-C SECS set cpu limit [default: inherited]\n\
|
||||
-M BYTES set virtual memory limit [default: 4gb]\n\
|
||||
-P PROCS set process limit [default: GetCpuCount()*2]\n\
|
||||
-O FILES set file descriptor limit [default: 64]\n\
|
||||
-P PROCS set process limit [default: preexisting + cpus]\n\
|
||||
-F BYTES set individual file size limit [default: 4gb]\n\
|
||||
-T pledge exits 0 if pledge() is supported by host system\n\
|
||||
-T unveil exits 0 if unveil() is supported by host system\n\
|
||||
|
@ -136,6 +138,7 @@ bool isdynamic;
|
|||
bool g_noclose;
|
||||
long g_cpuquota;
|
||||
long g_fszquota;
|
||||
long g_nfdquota;
|
||||
long g_memquota;
|
||||
long g_proquota;
|
||||
long g_dontdrop;
|
||||
|
@ -155,11 +158,16 @@ static void GetOpts(int argc, char *argv[]) {
|
|||
int opt;
|
||||
struct sysinfo si;
|
||||
g_promises = 0;
|
||||
g_nfdquota = 64;
|
||||
g_fszquota = 256 * 1000 * 1000;
|
||||
g_proquota = GetCpuCount() * 100;
|
||||
g_memquota = 4L * 1024 * 1024 * 1024;
|
||||
if (!sysinfo(&si)) g_memquota = si.totalram;
|
||||
while ((opt = getopt(argc, argv, "hnqkNVT:p:u:g:c:C:D:P:M:F:v:")) != -1) {
|
||||
if (!sysinfo(&si)) {
|
||||
g_memquota = si.totalram;
|
||||
g_proquota = GetCpuCount() + si.procs;
|
||||
} else {
|
||||
g_proquota = GetCpuCount() * 100;
|
||||
g_memquota = 4L * 1024 * 1024 * 1024;
|
||||
}
|
||||
while ((opt = getopt(argc, argv, "hnqkNVT:p:u:g:c:C:D:P:M:F:O:v:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
g_nice = true;
|
||||
|
@ -197,11 +205,24 @@ static void GetOpts(int argc, char *argv[]) {
|
|||
case 'P':
|
||||
g_proquota = atoi(optarg);
|
||||
break;
|
||||
case 'M':
|
||||
g_memquota = sizetol(optarg, 1024);
|
||||
case 'O':
|
||||
g_nfdquota = atoi(optarg);
|
||||
break;
|
||||
case 'F':
|
||||
errno = 0;
|
||||
g_fszquota = sizetol(optarg, 1000);
|
||||
if (errno) {
|
||||
kprintf("error: invalid size: -F %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
errno = 0;
|
||||
g_memquota = sizetol(optarg, 1024);
|
||||
if (errno) {
|
||||
kprintf("error: invalid size: -F %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (g_promises) {
|
||||
|
@ -232,10 +253,6 @@ const char *prog;
|
|||
char pathbuf[PATH_MAX];
|
||||
struct pollfd pfds[256];
|
||||
|
||||
int GetBaseCpuFreqMhz(void) {
|
||||
return KCPUIDS(16H, EAX) & 0x7fff;
|
||||
}
|
||||
|
||||
static bool SupportsLandlock(void) {
|
||||
int e = errno;
|
||||
bool r = landlock_create_ruleset(0, 0, LANDLOCK_CREATE_RULESET_VERSION) >= 0;
|
||||
|
@ -290,61 +307,27 @@ void NormalizeFileDescriptors(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void SetCpuLimit(int secs) {
|
||||
int SetLimit(int r, long lo, long hi) {
|
||||
struct rlimit old;
|
||||
struct rlimit lim = {lo, hi};
|
||||
if (r < 0 || r >= RLIM_NLIMITS) return 0;
|
||||
if (!setrlimit(r, &lim)) return 0;
|
||||
if (getrlimit(r, &old)) return -1;
|
||||
lim.rlim_cur = MIN(lim.rlim_cur, old.rlim_max);
|
||||
lim.rlim_max = MIN(lim.rlim_max, old.rlim_max);
|
||||
return setrlimit(r, &lim);
|
||||
}
|
||||
|
||||
int GetBaseCpuFreqMhz(void) {
|
||||
return KCPUIDS(16H, EAX) & 0x7fff;
|
||||
}
|
||||
|
||||
int SetCpuLimit(int secs) {
|
||||
int mhz, lim;
|
||||
struct rlimit rlim;
|
||||
if (secs <= 0) return;
|
||||
if (!(mhz = GetBaseCpuFreqMhz())) return;
|
||||
if (secs <= 0) return 0;
|
||||
if (!(mhz = GetBaseCpuFreqMhz())) return eopnotsupp();
|
||||
lim = ceil(3100. / mhz * secs);
|
||||
rlim.rlim_cur = lim;
|
||||
rlim.rlim_max = lim + 1;
|
||||
if (setrlimit(RLIMIT_CPU, &rlim) != -1) {
|
||||
return;
|
||||
} else if (getrlimit(RLIMIT_CPU, &rlim) != -1) {
|
||||
if (lim < rlim.rlim_cur) {
|
||||
rlim.rlim_cur = lim;
|
||||
if (setrlimit(RLIMIT_CPU, &rlim) != -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
kprintf("error: setrlimit(RLIMIT_CPU) failed: %m\n");
|
||||
exit(20);
|
||||
}
|
||||
|
||||
void SetFszLimit(long n) {
|
||||
struct rlimit rlim;
|
||||
if (n <= 0) return;
|
||||
rlim.rlim_cur = n;
|
||||
rlim.rlim_max = n << 1;
|
||||
if (setrlimit(RLIMIT_FSIZE, &rlim) != -1) {
|
||||
return;
|
||||
} else if (getrlimit(RLIMIT_FSIZE, &rlim) != -1) {
|
||||
rlim.rlim_cur = n;
|
||||
if (setrlimit(RLIMIT_FSIZE, &rlim) != -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
kprintf("error: setrlimit(RLIMIT_FSIZE) failed: %m\n");
|
||||
exit(21);
|
||||
}
|
||||
|
||||
void SetMemLimit(long n) {
|
||||
struct rlimit rlim = {n, n};
|
||||
if (n <= 0) return;
|
||||
if (setrlimit(RLIMIT_AS, &rlim) == -1) {
|
||||
kprintf("error: setrlimit(RLIMIT_AS) failed: %m\n");
|
||||
exit(22);
|
||||
}
|
||||
}
|
||||
|
||||
void SetProLimit(long n) {
|
||||
struct rlimit rlim = {n, n};
|
||||
if (n <= 0) return;
|
||||
if (setrlimit(RLIMIT_NPROC, &rlim) == -1) {
|
||||
kprintf("error: setrlimit(RLIMIT_NPROC) failed: %m\n");
|
||||
exit(22);
|
||||
}
|
||||
return SetLimit(RLIMIT_CPU, lim, lim);
|
||||
}
|
||||
|
||||
bool PathExists(const char *path) {
|
||||
|
@ -610,10 +593,26 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
// set resource limits
|
||||
MakeProcessNice();
|
||||
SetCpuLimit(g_cpuquota);
|
||||
SetFszLimit(g_fszquota);
|
||||
SetMemLimit(g_memquota);
|
||||
SetProLimit(g_proquota);
|
||||
|
||||
if (SetCpuLimit(g_cpuquota) == -1) {
|
||||
kprintf("error: setrlimit(%s) failed: %m\n", "RLIMIT_CPU");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (SetLimit(RLIMIT_FSIZE, g_fszquota, g_fszquota * 1.5) == -1) {
|
||||
kprintf("error: setrlimit(%s) failed: %m\n", "RLIMIT_FSIZE");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (SetLimit(RLIMIT_AS, g_memquota, g_memquota) == -1) {
|
||||
kprintf("error: setrlimit(%s) failed: %m\n", "RLIMIT_AS");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (SetLimit(RLIMIT_NPROC, g_proquota, g_proquota) == -1) {
|
||||
kprintf("error: setrlimit(%s) failed: %m\n", "RLIMIT_NPROC");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// test for weird chmod bits
|
||||
usergid = getgid();
|
||||
|
@ -786,6 +785,11 @@ int main(int argc, char *argv[]) {
|
|||
putenv(buf);
|
||||
}
|
||||
|
||||
if (SetLimit(RLIMIT_NOFILE, g_nfdquota, g_nfdquota) == -1) {
|
||||
kprintf("error: setrlimit(%s) failed: %m\n", "RLIMIT_NOFILE");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// apply sandbox
|
||||
if (pledge(g_promises, g_promises) == -1) {
|
||||
kprintf("error: pledge(%#s) failed: %m\n", g_promises);
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
(runs (format "o/$m/%s.com%s V=5 TESTARGS=-b" name runsuffix))
|
||||
(buns (format "o/$m/test/%s_test.com%s V=5 TESTARGS=-b" name runsuffix)))
|
||||
(cond ((not (member ext '("c" "cc" "s" "S" "rl" "f")))
|
||||
(format "m=%s; o//third_party/make/make.com -j12 -O MODE=$m o/$m/%s"
|
||||
(format "m=%s; make -j12 -O MODE=$m o/$m/%s"
|
||||
mode
|
||||
(directory-file-name
|
||||
(or (file-name-directory
|
||||
|
@ -200,7 +200,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "o//third_party/make/make.com -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
"scp $f $f.dbg win7:"
|
||||
"ssh win7 ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
|
@ -209,7 +209,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "o//third_party/make/make.com -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
"scp $f $f.dbg win10:"
|
||||
"ssh win10 ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
|
@ -218,19 +218,19 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "o//third_party/make/make.com -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
"scp $f $f.dbg xnu:"
|
||||
"ssh xnu ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((and (equal suffix "")
|
||||
(cosmo-contains "_test." (buffer-file-name)))
|
||||
(format "m=%s; o//third_party/make/make.com -j12 -O MODE=$m %s"
|
||||
(format "m=%s; make -j12 -O MODE=$m %s"
|
||||
mode runs))
|
||||
((and (equal suffix "")
|
||||
(file-exists-p (format "%s" buddy)))
|
||||
(format (cosmo-join
|
||||
" && "
|
||||
'("m=%s; n=%s; o//third_party/make/make.com -j12 -O o/$m/$n%s.o MODE=$m"
|
||||
'("m=%s; n=%s; make -j12 -O o/$m/$n%s.o MODE=$m"
|
||||
;; "bloat o/$m/%s.o | head"
|
||||
;; "nm -C --size o/$m/%s.o | sort -r"
|
||||
"echo"
|
||||
|
@ -242,11 +242,11 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "o//third_party/make/make.com -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
"./$f"))
|
||||
mode name))
|
||||
((eq kind 'test)
|
||||
(format `"m=%s; f=o/$m/%s.com.ok && o//third_party/make/make.com -j12 -O $f MODE=$m" mode name))
|
||||
(format `"m=%s; f=o/$m/%s.com.ok && make -j12 -O $f MODE=$m" mode name))
|
||||
((and (file-regular-p this)
|
||||
(file-executable-p this))
|
||||
(format "./%s" file))
|
||||
|
@ -255,7 +255,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s%s.o"
|
||||
,(concat "o//third_party/make/make.com -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
;; "nm -C --size $f | sort -r"
|
||||
"echo"
|
||||
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
|
||||
|
@ -626,11 +626,11 @@
|
|||
((eq major-mode 'lua-mode)
|
||||
(let* ((mode (cosmo--make-mode arg))
|
||||
(redbean ))
|
||||
(compile (format "o//third_party/make/make.com -j16 MODE=%s o/%s/tool/net/redbean.com && o/%s/tool/net/redbean.com -i %s" mode mode mode file))))
|
||||
(compile (format "make -j16 MODE=%s o/%s/tool/net/redbean.com && o/%s/tool/net/redbean.com -i %s" mode mode mode file))))
|
||||
((and (eq major-mode 'python-mode)
|
||||
(cosmo-startswith "third_party/python/Lib/test/" file))
|
||||
(let ((mode (cosmo--make-mode arg)))
|
||||
(compile (format "o//third_party/make/make.com -j12 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
|
||||
(compile (format "make -j12 MODE=%s PYHARNESSARGS=-vv PYTESTARGS=-v o/%s/%s.py.runs"
|
||||
mode mode (file-name-sans-extension file)))))
|
||||
((eq major-mode 'python-mode)
|
||||
(compile (format "python.com %s" file)))
|
||||
|
|
Loading…
Reference in a new issue