mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +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
|
# - tool/build/runitd.c
|
||||||
|
|
||||||
.PRECIOUS: o/$(MODE)/%.com.ok
|
.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)/%.com.ok: \
|
||||||
o/$(MODE)/tool/build/runit.com \
|
o/$(MODE)/tool/build/runit.com \
|
||||||
o/$(MODE)/tool/build/runitd.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 (setrlimit(resource, &lim) == -1) {
|
||||||
if (!getrlimit(resource, &old)) {
|
if (!getrlimit(resource, &old)) {
|
||||||
lim.rlim_max = MIN(hard, old.rlim_max);
|
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)) {
|
if (!setrlimit(resource, &lim)) {
|
||||||
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
|
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
|
||||||
DescribeRlimitName(resource), lim.rlim_cur, lim.rlim_max);
|
DescribeRlimitName(resource), lim.rlim_cur, lim.rlim_max);
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/struct/itimerval.h"
|
#include "libc/calls/struct/itimerval.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/math.h"
|
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/itimer.h"
|
#include "libc/sysv/consts/itimer.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/intrin/safemacros.internal.h"
|
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/termios.h"
|
#include "libc/calls/termios.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
|
#include "libc/intrin/safemacros.internal.h"
|
||||||
#include "libc/log/internal.h"
|
#include "libc/log/internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -36,8 +36,8 @@
|
||||||
*/
|
*/
|
||||||
int getttysize(int fd, struct winsize *out) {
|
int getttysize(int fd, struct winsize *out) {
|
||||||
if (__nocolor) {
|
if (__nocolor) {
|
||||||
out->ws_col = strtoimax(firstnonnull(getenv("COLUMNS"), "80"), NULL, 0);
|
out->ws_col = atoi(firstnonnull(getenv("COLUMNS"), "80"));
|
||||||
out->ws_row = strtoimax(firstnonnull(getenv("ROWS"), "40"), NULL, 0);
|
out->ws_row = atoi(firstnonnull(getenv("ROWS"), "40"));
|
||||||
out->ws_xpixel = 0;
|
out->ws_xpixel = 0;
|
||||||
out->ws_ypixel = 0;
|
out->ws_ypixel = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/struct/pollfd.h"
|
#include "libc/sock/struct/pollfd.h"
|
||||||
|
#include "libc/sock/struct/pollfd.internal.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/poll.h"
|
#include "libc/sysv/consts/poll.h"
|
||||||
#include "libc/sysv/consts/sig.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
|
* on both sockets and files at the same time. We also poll for signals
|
||||||
* while poll is polling.
|
* 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;
|
bool ok;
|
||||||
uint32_t avail;
|
uint32_t avail;
|
||||||
|
sigset_t oldmask;
|
||||||
struct sys_pollfd_nt pipefds[8];
|
struct sys_pollfd_nt pipefds[8];
|
||||||
struct sys_pollfd_nt sockfds[64];
|
struct sys_pollfd_nt sockfds[64];
|
||||||
int pipeindices[ARRAYLEN(pipefds)];
|
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;
|
int i, sn, pn, failed, gotinvals, gotpipes, gotsocks, waitfor;
|
||||||
|
|
||||||
// check for interrupts early before doing work
|
// 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();
|
if (_check_interrupts(false, g_fds.p)) return eintr();
|
||||||
|
|
||||||
// do the planning
|
// do the planning
|
||||||
|
|
|
@ -81,7 +81,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
millis = timeout_ms;
|
millis = timeout_ms;
|
||||||
rc = sys_poll_nt(fds, nfds, &millis);
|
rc = sys_poll_nt(fds, nfds, &millis, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SYSDEBUG) && _POLLTRACE
|
#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/conv.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
static int GetExponent(int c) {
|
static int GetExponent(int c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -65,27 +66,41 @@ static int GetExponent(int c) {
|
||||||
* characters after it (e.g. kbit, Mibit, TiB) are ignored. Spaces
|
* characters after it (e.g. kbit, Mibit, TiB) are ignored. Spaces
|
||||||
* before the integer are ignored, and overflows will be detected.
|
* 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 s is non-null nul-terminated input string
|
||||||
* @param b is multiplier which should be 1000 or 1024
|
* @param b is multiplier which should be 1000 or 1024
|
||||||
* @return size greater than or equal 0 or -1 on error
|
* @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 sizetol(const char *s, long b) {
|
||||||
long x;
|
long x;
|
||||||
int c, e;
|
int c, e, d;
|
||||||
do {
|
do {
|
||||||
c = *s++;
|
c = *s++;
|
||||||
} while (c == ' ' || c == '\t');
|
} 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;
|
x = 0;
|
||||||
do {
|
do {
|
||||||
if (__builtin_mul_overflow(x, 10, &x) ||
|
if (__builtin_mul_overflow(x, 10, &x) ||
|
||||||
__builtin_add_overflow(x, c - '0', &x)) {
|
__builtin_add_overflow(x, (c - '0') * d, &x)) {
|
||||||
return -1;
|
return eoverflow();
|
||||||
}
|
}
|
||||||
} while (isdigit((c = *s++)));
|
} while (isdigit((c = *s++)));
|
||||||
if ((e = GetExponent(c)) == -1) return -1;
|
if ((e = GetExponent(c)) == -1) {
|
||||||
|
return einval();
|
||||||
|
}
|
||||||
while (e--) {
|
while (e--) {
|
||||||
if (__builtin_mul_overflow(x, b, &x)) return -1;
|
if (__builtin_mul_overflow(x, b, &x)) {
|
||||||
|
return eoverflow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/fmt/fmt.h"
|
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/intrin/safemacros.internal.h"
|
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/intrin/safemacros.internal.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nt/enum/formatmessageflags.h"
|
#include "libc/nt/enum/formatmessageflags.h"
|
||||||
#include "libc/nt/enum/lang.h"
|
#include "libc/nt/enum/lang.h"
|
||||||
|
|
|
@ -36,6 +36,7 @@ COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
extern FILE *__log_file;
|
extern FILE *__log_file;
|
||||||
|
|
||||||
|
int __watch(void *, size_t);
|
||||||
void __die(void) relegated wontreturn; /* print backtrace and abort() */
|
void __die(void) relegated wontreturn; /* print backtrace and abort() */
|
||||||
void meminfo(int); /* shows malloc statistics &c. */
|
void meminfo(int); /* shows malloc statistics &c. */
|
||||||
void memsummary(int); /* light version of same thing */
|
void memsummary(int); /* light version of same thing */
|
||||||
|
|
|
@ -65,6 +65,10 @@ o/$(MODE)/libc/log/checkfail.o: private \
|
||||||
OVERRIDE_CFLAGS += \
|
OVERRIDE_CFLAGS += \
|
||||||
-mgeneral-regs-only
|
-mgeneral-regs-only
|
||||||
|
|
||||||
|
o/$(MODE)/libc/log/watch.o: private \
|
||||||
|
OVERRIDE_CFLAGS += \
|
||||||
|
-ffreestanding
|
||||||
|
|
||||||
o/$(MODE)/libc/log/attachdebugger.o \
|
o/$(MODE)/libc/log/attachdebugger.o \
|
||||||
o/$(MODE)/libc/log/checkaligned.o \
|
o/$(MODE)/libc/log/checkaligned.o \
|
||||||
o/$(MODE)/libc/log/checkfail.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 += \
|
OVERRIDE_CFLAGS += \
|
||||||
-Os
|
-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_LIBS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)))
|
||||||
LIBC_RUNTIME_SRCS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_SRCS))
|
LIBC_RUNTIME_SRCS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_SRCS))
|
||||||
LIBC_RUNTIME_HDRS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_HDRS))
|
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_dgram(int, int, int, int[2]) hidden;
|
||||||
*/
|
*/
|
||||||
int sys_socketpair_nt(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 __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *,
|
||||||
size_t) hidden;
|
size_t) hidden;
|
||||||
|
|
|
@ -18,9 +18,13 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/calls/struct/timespec.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/intrin/describeflags.internal.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/select.h"
|
#include "libc/sock/select.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does what poll() does except with bitset API.
|
* 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) {
|
const struct timespec *timeout, const sigset_t *sigmask) {
|
||||||
int rc;
|
int rc;
|
||||||
sigset_t oldmask;
|
sigset_t oldmask;
|
||||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
struct timeval tv, *tvp;
|
||||||
POLLTRACE("pselect(%d, %p, %p, %p, [%s], %s) → %d% m", nfds, readfds,
|
if (nfds < 0) {
|
||||||
writefds, exceptfds, DescribeTimeval(rc, timeout),
|
rc = einval();
|
||||||
DescribeSigset(0, sigmask), rc);
|
} 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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/state.internal.h"
|
||||||
#include "libc/calls/struct/timeval.h"
|
#include "libc/calls/struct/timeval.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/sock/select.h"
|
#include "libc/sock/select.h"
|
||||||
|
@ -27,14 +28,12 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
|
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;
|
uint64_t millis;
|
||||||
int i, pfds, events, fdcount;
|
int i, pfds, events, fdcount;
|
||||||
struct pollfd fds[64];
|
struct pollfd fds[64];
|
||||||
|
|
||||||
// check for interrupts early before doing work
|
|
||||||
if (_check_interrupts(false, g_fds.p)) return eintr();
|
|
||||||
|
|
||||||
// convert bitsets to pollfd
|
// convert bitsets to pollfd
|
||||||
for (pfds = i = 0; i < nfds; ++i) {
|
for (pfds = i = 0; i < nfds; ++i) {
|
||||||
events = 0;
|
events = 0;
|
||||||
|
@ -60,7 +59,7 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
|
||||||
}
|
}
|
||||||
|
|
||||||
// call our nt poll implementation
|
// 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;
|
if (fdcount == -1) return -1;
|
||||||
|
|
||||||
// convert pollfd back to bitsets
|
// convert pollfd back to bitsets
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/calls/struct/timeval.h"
|
#include "libc/calls/struct/timeval.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/select.h"
|
#include "libc/sock/select.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does what poll() does except with bitset API.
|
* 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;
|
int rc;
|
||||||
POLLTRACE("select(%d, %p, %p, %p, %s) → ...", nfds, readfds, writefds,
|
POLLTRACE("select(%d, %p, %p, %p, %s) → ...", nfds, readfds, writefds,
|
||||||
exceptfds, DescribeTimeval(0, timeout));
|
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);
|
rc = sys_select(nfds, readfds, writefds, exceptfds, timeout);
|
||||||
} else {
|
} 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,
|
POLLTRACE("select(%d, %p, %p, %p, [%s]) → %d% m", nfds, readfds, writefds,
|
||||||
exceptfds, DescribeTimeval(rc, timeout), rc);
|
exceptfds, DescribeTimeval(rc, timeout), rc);
|
||||||
|
|
|
@ -11,13 +11,14 @@
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
typedef struct fd_set {
|
typedef struct fd_set {
|
||||||
uint64_t fds_bits[FD_SETSIZE / 64];
|
unsigned long fds_bits[FD_SETSIZE / (sizeof(long) * CHAR_BIT)];
|
||||||
} fd_set;
|
} fd_set;
|
||||||
|
|
||||||
#define FD_ISSET(FD, SET) (((SET)->fds_bits[(FD) >> 6] >> ((FD)&63)) & 1)
|
#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_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_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_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 select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
||||||
int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
|
int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_INTERNAL_H_
|
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_INTERNAL_H_
|
||||||
#define 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"
|
#include "libc/sock/struct/pollfd.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
int32_t sys_poll(struct pollfd *, uint64_t, signed) hidden;
|
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_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_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -105,7 +105,7 @@ static void EmptySignalMask(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FixIrregularFds(void) {
|
static void FixIrregularFds(void) {
|
||||||
int i, fd, maxfds;
|
int e, i, fd, maxfds;
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
struct pollfd *pfds;
|
struct pollfd *pfds;
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
|
@ -118,6 +118,9 @@ static void FixIrregularFds(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
e = errno;
|
||||||
|
if (!closefrom(3)) return;
|
||||||
|
errno = e;
|
||||||
if (IsWindows()) {
|
if (IsWindows()) {
|
||||||
maxfds = 64;
|
maxfds = 64;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
@ -24,7 +25,10 @@ TEST(sizetol, test) {
|
||||||
EXPECT_EQ(0, sizetol("0", 1000));
|
EXPECT_EQ(0, sizetol("0", 1000));
|
||||||
EXPECT_EQ(0, sizetol("0kb", 1000));
|
EXPECT_EQ(0, sizetol("0kb", 1000));
|
||||||
EXPECT_EQ(31337, sizetol("31337", 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(-1000, sizetol("-1kb", 1000));
|
||||||
EXPECT_EQ(2000, sizetol("2k", 1000));
|
EXPECT_EQ(2000, sizetol("2k", 1000));
|
||||||
EXPECT_EQ(1024, sizetol("1kb", 1024));
|
EXPECT_EQ(1024, sizetol("1kb", 1024));
|
||||||
EXPECT_EQ(2048, sizetol("2k", 1024));
|
EXPECT_EQ(2048, sizetol("2k", 1024));
|
||||||
|
@ -43,11 +47,13 @@ TEST(sizetol, test) {
|
||||||
EXPECT_EQ(100, sizetol("\t100\t", 1024));
|
EXPECT_EQ(100, sizetol("\t100\t", 1024));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(sizetol, testNegative_notAllowed) {
|
|
||||||
EXPECT_EQ(-1, sizetol("-23", 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(sizetol, testOverflow_isDetected) {
|
TEST(sizetol, testOverflow_isDetected) {
|
||||||
EXPECT_EQ(9000000000000000000, sizetol("9eb", 1000));
|
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)
|
@$(APELINK)
|
||||||
|
|
||||||
o/$(MODE)/test/libc/sock/unix_test.com.runs: \
|
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/setsockopt_test.com.runs \
|
||||||
o/$(MODE)/test/libc/sock/sendfile_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/poll_test.com.runs \
|
||||||
o/$(MODE)/test/libc/sock/pollfd_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/sendrecvmsg_test.com.runs \
|
||||||
o/$(MODE)/test/libc/sock/nointernet_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
|
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
||||||
|
|
||||||
|
|
|
@ -71,10 +71,10 @@ o/$(MODE)/test/tool/net/%.com.dbg: \
|
||||||
@$(APELINK)
|
@$(APELINK)
|
||||||
|
|
||||||
o/$(MODE)/test/tool/net/redbean_test.com.runs: \
|
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: \
|
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
|
.PHONY: o/$(MODE)/test/tool/net
|
||||||
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
|
- .UNSANDBOXED variable to disable pledge / unveil
|
||||||
- .CPU variable which tunes CPU rlimit in seconds
|
- .CPU variable which tunes CPU rlimit in seconds
|
||||||
- .MEMORY variable for virtual memory limit, e.g. 512m
|
- .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
|
- .FSIZE variable which tunes max file size, e.g. 1g
|
||||||
- .NPROC variable which tunes fork() / clone() limit
|
- .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
|
- Do automatic setup and teardown of TMPDIR per rule
|
||||||
- Remove code that forces slow path if not using /bin/sh
|
- Remove code that forces slow path if not using /bin/sh
|
||||||
- Remove 200,000 lines of VAX/OS2/DOS/AMIGA/etc. code
|
- 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. */
|
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
||||||
#include "libc/calls/calls.h"
|
#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 to the number of bits in type 'ptrdiff_t'. */
|
||||||
#define BITSIZEOF_PTRDIFF_T 64
|
#define BITSIZEOF_PTRDIFF_T 64
|
||||||
|
|
||||||
|
@ -401,7 +291,7 @@
|
||||||
#define HAVE_POSIX_SPAWNATTR_SETSIGMASK 1
|
#define HAVE_POSIX_SPAWNATTR_SETSIGMASK 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `pselect' function. */
|
/* 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. */
|
/* Define to 1 if you have the `pstat_getdynamic' function. */
|
||||||
/* #undef HAVE_PSTAT_GETDYNAMIC */
|
/* #undef HAVE_PSTAT_GETDYNAMIC */
|
||||||
|
@ -425,7 +315,7 @@
|
||||||
#define HAVE_SETEUID 1
|
#define HAVE_SETEUID 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `setlinebuf' function. */
|
/* 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 to 1 if you have the `setregid' function. */
|
||||||
#define HAVE_SETREGID 1
|
#define HAVE_SETREGID 1
|
||||||
|
@ -451,12 +341,6 @@
|
||||||
/* Define to 1 if 'wint_t' is a signed integer type. */
|
/* Define to 1 if 'wint_t' is a signed integer type. */
|
||||||
/* #undef HAVE_SIGNED_WINT_T */
|
/* #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 to 1 if you have the <spawn.h> header file. */
|
||||||
#define HAVE_SPAWN_H 1
|
#define HAVE_SPAWN_H 1
|
||||||
|
|
||||||
|
@ -623,7 +507,11 @@
|
||||||
#define MAKE_HOST "x86_64-cosmopolitan"
|
#define MAKE_HOST "x86_64-cosmopolitan"
|
||||||
|
|
||||||
/* Define to 1 to enable job server support in GNU make. */
|
/* 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 MAKE_JOBSERVER 1 */
|
||||||
|
|
||||||
/* Define to 1 to enable symbolic link timestamp checking. */
|
/* 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/o.h"
|
||||||
#include "libc/sysv/consts/pr.h"
|
#include "libc/sysv/consts/pr.h"
|
||||||
#include "libc/sysv/consts/prot.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/time/time.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
#include "third_party/libcxx/math.h"
|
#include "third_party/libcxx/math.h"
|
||||||
|
@ -416,7 +418,7 @@ get_target_variable (const char *name,
|
||||||
const char *
|
const char *
|
||||||
get_tmpdir (struct file *file)
|
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 *
|
char *
|
||||||
|
@ -1798,61 +1800,28 @@ get_base_cpu_freq_mhz (void)
|
||||||
return KCPUIDS(16H, EAX) & 0x7fff;
|
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)
|
set_cpu_limit (int secs)
|
||||||
{
|
{
|
||||||
int mhz, lim;
|
int mhz, lim;
|
||||||
struct rlimit rlim;
|
if (secs <= 0) return 0;
|
||||||
if (secs <= 0) return;
|
if (!(mhz = get_base_cpu_freq_mhz())) return eopnotsupp();
|
||||||
if (IsWindows()) return;
|
|
||||||
if (!(mhz = get_base_cpu_freq_mhz())) return;
|
|
||||||
lim = ceil(3100. / mhz * secs);
|
lim = ceil(3100. / mhz * secs);
|
||||||
rlim.rlim_cur = lim;
|
return set_limit (RLIMIT_CPU, lim, lim + 1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sysinfo g_sysinfo;
|
static struct sysinfo g_sysinfo;
|
||||||
|
@ -1920,18 +1889,18 @@ child_execute_job (struct childbase *child,
|
||||||
}
|
}
|
||||||
|
|
||||||
internet = parse_bool (get_target_variable
|
internet = parse_bool (get_target_variable
|
||||||
(STRING_SIZE_TUPLE(".INTERNET"),
|
(STRING_SIZE_TUPLE (".INTERNET"),
|
||||||
c ? c->file : 0, "0"));
|
c ? c->file : 0, "0"));
|
||||||
|
|
||||||
unsandboxed = parse_bool (get_target_variable
|
unsandboxed = parse_bool (get_target_variable
|
||||||
(STRING_SIZE_TUPLE(".UNSANDBOXED"),
|
(STRING_SIZE_TUPLE (".UNSANDBOXED"),
|
||||||
c ? c->file : 0, "0"));
|
c ? c->file : 0, "0"));
|
||||||
|
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
sandboxed = !unsandboxed;
|
sandboxed = !unsandboxed;
|
||||||
strict = parse_bool (get_target_variable
|
strict = parse_bool (get_target_variable
|
||||||
(STRING_SIZE_TUPLE(".STRICT"),
|
(STRING_SIZE_TUPLE (".STRICT"),
|
||||||
c->file, "0"));
|
c->file, "0"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1943,7 +1912,7 @@ child_execute_job (struct childbase *child,
|
||||||
if (!unsandboxed)
|
if (!unsandboxed)
|
||||||
{
|
{
|
||||||
promises = emptytonull (get_target_variable
|
promises = emptytonull (get_target_variable
|
||||||
(STRING_SIZE_TUPLE(".PLEDGE"),
|
(STRING_SIZE_TUPLE (".PLEDGE"),
|
||||||
c ? c->file : 0, 0));
|
c ? c->file : 0, 0));
|
||||||
if (promises)
|
if (promises)
|
||||||
promises = xstrdup (promises);
|
promises = xstrdup (promises);
|
||||||
|
@ -1968,52 +1937,158 @@ child_execute_job (struct childbase *child,
|
||||||
internet ? " with internet access" : ""));
|
internet ? " with internet access" : ""));
|
||||||
|
|
||||||
/* [jart] Set cpu seconds quota. */
|
/* [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)))
|
c ? c->file : 0, 0)))
|
||||||
{
|
{
|
||||||
int secs;
|
int secs;
|
||||||
secs = atoi (s);
|
secs = atoi (s);
|
||||||
DB (DB_JOBS, (_("Setting cpu limit of %d seconds\n"), secs));
|
if (!set_cpu_limit (secs))
|
||||||
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. */
|
/* [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)))
|
c ? c->file : 0, 0)))
|
||||||
{
|
{
|
||||||
long bytes;
|
long bytes;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
errno = 0;
|
||||||
if (!strchr (s, '%'))
|
if (!strchr (s, '%'))
|
||||||
bytes = sizetol (s, 1024);
|
bytes = sizetol (s, 1024);
|
||||||
else
|
else
|
||||||
bytes = strtod (s, 0) / 100. * g_sysinfo.totalram;
|
bytes = strtod (s, 0) / 100. * g_sysinfo.totalram;
|
||||||
DB (DB_JOBS, (_("Setting virtual memory limit of %s\n"),
|
if (bytes > 0)
|
||||||
(FormatMemorySize (buf, bytes, 1024), buf)));
|
{
|
||||||
set_mem_limit (bytes);
|
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. */
|
/* [jart] Set resident memory quota. */
|
||||||
if ((s = get_target_variable (STRING_SIZE_TUPLE(".FSIZE"),
|
if (RLIMIT_RSS < RLIM_NLIMITS &&
|
||||||
|
(s = get_target_variable (STRING_SIZE_TUPLE (".RSS"),
|
||||||
c ? c->file : 0, 0)))
|
c ? c->file : 0, 0)))
|
||||||
{
|
{
|
||||||
long bytes;
|
long bytes;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
bytes = sizetol (s, 1000);
|
errno = 0;
|
||||||
DB (DB_JOBS, (_("Setting file size limit of %s\n"),
|
if (!strchr (s, '%'))
|
||||||
(FormatMemorySize (buf, bytes, 1000), buf)));
|
bytes = sizetol (s, 1024);
|
||||||
set_fsz_limit (bytes);
|
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. */
|
/* [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)))
|
c ? c->file : 0, 0)))
|
||||||
{
|
{
|
||||||
int procs;
|
int procs;
|
||||||
if ((procs = atoi (s)) > 0)
|
if ((procs = atoi (s)) > 0)
|
||||||
{
|
{
|
||||||
DB (DB_JOBS, (_("Setting process limit to %d + %d preexisting\n"),
|
if (!set_limit (RLIMIT_NPROC,
|
||||||
procs, g_sysinfo.procs));
|
procs + g_sysinfo.procs,
|
||||||
set_pro_limit (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_STDIO \
|
||||||
LIBC_STR \
|
LIBC_STR \
|
||||||
LIBC_SOCK \
|
LIBC_SOCK \
|
||||||
|
LIBC_NT_KERNEL32 \
|
||||||
LIBC_SYSV \
|
LIBC_SYSV \
|
||||||
LIBC_SYSV_CALLS \
|
LIBC_SYSV_CALLS \
|
||||||
LIBC_TIME \
|
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
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program. If not, see <http://www.gnu.org/licenses/>. */
|
this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include "libc/mem/alg.h"
|
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/makedev.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/limits.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/mem/alg.h"
|
||||||
#include "libc/mem/alloca.h"
|
#include "libc/mem/alloca.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/stdio/temp.h"
|
#include "libc/stdio/temp.h"
|
||||||
|
#include "libc/str/locale.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/f.h"
|
#include "libc/sysv/consts/f.h"
|
||||||
#include "libc/sysv/consts/o.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/s.h"
|
||||||
#include "libc/sysv/consts/sa.h"
|
#include "libc/sysv/consts/sa.h"
|
||||||
#include "libc/sysv/consts/sicode.h"
|
#include "libc/sysv/consts/sicode.h"
|
||||||
#include "libc/sysv/consts/utime.h"
|
|
||||||
#include "libc/sysv/consts/w.h"
|
#include "libc/sysv/consts/w.h"
|
||||||
#include "libc/time/struct/tm.h"
|
#include "libc/time/struct/tm.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/str/locale.h"
|
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
#include "third_party/gdtoa/gdtoa.h"
|
#include "third_party/gdtoa/gdtoa.h"
|
||||||
#include "third_party/musl/glob.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 "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/sa.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "third_party/make/config.h"
|
||||||
#include "third_party/make/debug.h"
|
#include "third_party/make/debug.h"
|
||||||
#include "third_party/make/job.h"
|
#include "third_party/make/job.h"
|
||||||
#include "third_party/make/os.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) {
|
static void set_child_handler_action_flags(int set_handler, int set_alarm) {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
#ifdef __EMX__
|
|
||||||
/* The child handler must be turned off here. */
|
|
||||||
signal(SIGCHLD, SIG_DFL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memset(&sa, '\0', sizeof sa);
|
memset(&sa, '\0', sizeof sa);
|
||||||
sa.sa_handler = child_handler;
|
sa.sa_handler = child_handler;
|
||||||
sa.sa_flags = set_handler ? 0 : SA_RESTART;
|
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. */
|
/* Set file descriptors to be inherited / not inherited by subprocesses. */
|
||||||
|
|
||||||
#if !defined(F_SETFD) || !defined(F_GETFD)
|
#if !defined(F_SETFD) || !defined(F_GETFD)
|
||||||
void fd_inherit(int fd) {
|
void fd_inherit(int fd) {}
|
||||||
}
|
void fd_noinherit(int fd) {}
|
||||||
void fd_noinherit(int fd) {
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifndef FD_CLOEXEC
|
#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
|
/usr/local/etc/mime.types
|
||||||
|
|
||||||
o/$(MODE)/third_party/python/Lib/test/test_epoll.py.runs: \
|
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: \
|
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: \
|
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: \
|
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/Lib/test/test_grammar.py.runs: \
|
||||||
o/$(MODE)/third_party/python/pythontester.com
|
o/$(MODE)/third_party/python/pythontester.com
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ 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/calls.h"
|
||||||
#include "libc/calls/copyfile.h"
|
#include "libc/calls/copyfile.h"
|
||||||
#include "libc/calls/ioctl.h"
|
#include "libc/calls/ioctl.h"
|
||||||
|
@ -32,12 +29,15 @@
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/intrin/safemacros.internal.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/log/color.internal.h"
|
#include "libc/log/color.internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/math.h"
|
#include "libc/math.h"
|
||||||
|
#include "libc/mem/alg.h"
|
||||||
#include "libc/mem/io.h"
|
#include "libc/mem/io.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/nexgen32e/kcpuids.h"
|
#include "libc/nexgen32e/kcpuids.h"
|
||||||
|
@ -505,7 +505,7 @@ void SetFszLimit(long n) {
|
||||||
if (n <= 0) return;
|
if (n <= 0) return;
|
||||||
if (IsWindows()) return;
|
if (IsWindows()) return;
|
||||||
rlim.rlim_cur = n;
|
rlim.rlim_cur = n;
|
||||||
rlim.rlim_max = n << 1;
|
rlim.rlim_max = n + (n >> 1);
|
||||||
if (setrlimit(RLIMIT_FSIZE, &rlim) == -1) {
|
if (setrlimit(RLIMIT_FSIZE, &rlim) == -1) {
|
||||||
if (getrlimit(RLIMIT_FSIZE, &rlim) == -1) return;
|
if (getrlimit(RLIMIT_FSIZE, &rlim) == -1) return;
|
||||||
rlim.rlim_cur = n;
|
rlim.rlim_cur = n;
|
||||||
|
@ -1191,7 +1191,10 @@ int main(int argc, char *argv[]) {
|
||||||
if (!(exitcode = WEXITSTATUS(ws)) || exitcode == 254) {
|
if (!(exitcode = WEXITSTATUS(ws)) || exitcode == 254) {
|
||||||
if (touchtarget && target) {
|
if (touchtarget && target) {
|
||||||
makedirs(xdirname(target), 0755);
|
makedirs(xdirname(target), 0755);
|
||||||
touch(target, 0644);
|
if (touch(target, 0644)) {
|
||||||
|
exitcode = 90;
|
||||||
|
appends(&output, "\nfailed to touch output file\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (movepath) {
|
if (movepath) {
|
||||||
if (!MovePreservingDestinationInode(tmpout, movepath)) {
|
if (!MovePreservingDestinationInode(tmpout, movepath)) {
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/intrin/bits.h"
|
|
||||||
#include "libc/intrin/safemacros.internal.h"
|
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/landlock.h"
|
#include "libc/calls/landlock.h"
|
||||||
#include "libc/calls/pledge.h"
|
#include "libc/calls/pledge.h"
|
||||||
|
@ -34,8 +32,10 @@
|
||||||
#include "libc/elf/struct/ehdr.h"
|
#include "libc/elf/struct/ehdr.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/intrin/promises.internal.h"
|
#include "libc/intrin/promises.internal.h"
|
||||||
|
#include "libc/intrin/safemacros.internal.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/math.h"
|
#include "libc/math.h"
|
||||||
#include "libc/mem/io.h"
|
#include "libc/mem/io.h"
|
||||||
|
@ -56,6 +56,7 @@
|
||||||
#include "libc/sysv/consts/pr.h"
|
#include "libc/sysv/consts/pr.h"
|
||||||
#include "libc/sysv/consts/prio.h"
|
#include "libc/sysv/consts/prio.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
#include "libc/sysv/consts/rlim.h"
|
||||||
#include "libc/sysv/consts/rlimit.h"
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
#include "libc/sysv/consts/sched.h"
|
#include "libc/sysv/consts/sched.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
@ -86,7 +87,8 @@ usage: pledge.com [-hnN] PROG ARGS...\n\
|
||||||
-N don't normalize file descriptors\n\
|
-N don't normalize file descriptors\n\
|
||||||
-C SECS set cpu limit [default: inherited]\n\
|
-C SECS set cpu limit [default: inherited]\n\
|
||||||
-M BYTES set virtual memory limit [default: 4gb]\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\
|
-F BYTES set individual file size limit [default: 4gb]\n\
|
||||||
-T pledge exits 0 if pledge() is supported by host system\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\
|
-T unveil exits 0 if unveil() is supported by host system\n\
|
||||||
|
@ -136,6 +138,7 @@ bool isdynamic;
|
||||||
bool g_noclose;
|
bool g_noclose;
|
||||||
long g_cpuquota;
|
long g_cpuquota;
|
||||||
long g_fszquota;
|
long g_fszquota;
|
||||||
|
long g_nfdquota;
|
||||||
long g_memquota;
|
long g_memquota;
|
||||||
long g_proquota;
|
long g_proquota;
|
||||||
long g_dontdrop;
|
long g_dontdrop;
|
||||||
|
@ -155,11 +158,16 @@ static void GetOpts(int argc, char *argv[]) {
|
||||||
int opt;
|
int opt;
|
||||||
struct sysinfo si;
|
struct sysinfo si;
|
||||||
g_promises = 0;
|
g_promises = 0;
|
||||||
|
g_nfdquota = 64;
|
||||||
g_fszquota = 256 * 1000 * 1000;
|
g_fszquota = 256 * 1000 * 1000;
|
||||||
g_proquota = GetCpuCount() * 100;
|
if (!sysinfo(&si)) {
|
||||||
g_memquota = 4L * 1024 * 1024 * 1024;
|
g_memquota = si.totalram;
|
||||||
if (!sysinfo(&si)) g_memquota = si.totalram;
|
g_proquota = GetCpuCount() + si.procs;
|
||||||
while ((opt = getopt(argc, argv, "hnqkNVT:p:u:g:c:C:D:P:M:F:v:")) != -1) {
|
} 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) {
|
switch (opt) {
|
||||||
case 'n':
|
case 'n':
|
||||||
g_nice = true;
|
g_nice = true;
|
||||||
|
@ -197,11 +205,24 @@ static void GetOpts(int argc, char *argv[]) {
|
||||||
case 'P':
|
case 'P':
|
||||||
g_proquota = atoi(optarg);
|
g_proquota = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'O':
|
||||||
g_memquota = sizetol(optarg, 1024);
|
g_nfdquota = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
|
errno = 0;
|
||||||
g_fszquota = sizetol(optarg, 1000);
|
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;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if (g_promises) {
|
if (g_promises) {
|
||||||
|
@ -232,10 +253,6 @@ const char *prog;
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX];
|
||||||
struct pollfd pfds[256];
|
struct pollfd pfds[256];
|
||||||
|
|
||||||
int GetBaseCpuFreqMhz(void) {
|
|
||||||
return KCPUIDS(16H, EAX) & 0x7fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool SupportsLandlock(void) {
|
static bool SupportsLandlock(void) {
|
||||||
int e = errno;
|
int e = errno;
|
||||||
bool r = landlock_create_ruleset(0, 0, LANDLOCK_CREATE_RULESET_VERSION) >= 0;
|
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;
|
int mhz, lim;
|
||||||
struct rlimit rlim;
|
if (secs <= 0) return 0;
|
||||||
if (secs <= 0) return;
|
if (!(mhz = GetBaseCpuFreqMhz())) return eopnotsupp();
|
||||||
if (!(mhz = GetBaseCpuFreqMhz())) return;
|
|
||||||
lim = ceil(3100. / mhz * secs);
|
lim = ceil(3100. / mhz * secs);
|
||||||
rlim.rlim_cur = lim;
|
return SetLimit(RLIMIT_CPU, lim, 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathExists(const char *path) {
|
bool PathExists(const char *path) {
|
||||||
|
@ -610,10 +593,26 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
// set resource limits
|
// set resource limits
|
||||||
MakeProcessNice();
|
MakeProcessNice();
|
||||||
SetCpuLimit(g_cpuquota);
|
|
||||||
SetFszLimit(g_fszquota);
|
if (SetCpuLimit(g_cpuquota) == -1) {
|
||||||
SetMemLimit(g_memquota);
|
kprintf("error: setrlimit(%s) failed: %m\n", "RLIMIT_CPU");
|
||||||
SetProLimit(g_proquota);
|
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
|
// test for weird chmod bits
|
||||||
usergid = getgid();
|
usergid = getgid();
|
||||||
|
@ -786,6 +785,11 @@ int main(int argc, char *argv[]) {
|
||||||
putenv(buf);
|
putenv(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SetLimit(RLIMIT_NOFILE, g_nfdquota, g_nfdquota) == -1) {
|
||||||
|
kprintf("error: setrlimit(%s) failed: %m\n", "RLIMIT_NOFILE");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// apply sandbox
|
// apply sandbox
|
||||||
if (pledge(g_promises, g_promises) == -1) {
|
if (pledge(g_promises, g_promises) == -1) {
|
||||||
kprintf("error: pledge(%#s) failed: %m\n", g_promises);
|
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))
|
(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)))
|
(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")))
|
(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
|
mode
|
||||||
(directory-file-name
|
(directory-file-name
|
||||||
(or (file-name-directory
|
(or (file-name-directory
|
||||||
|
@ -200,7 +200,7 @@
|
||||||
(cosmo-join
|
(cosmo-join
|
||||||
" && "
|
" && "
|
||||||
`("m=%s; f=o/$m/%s.com"
|
`("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:"
|
"scp $f $f.dbg win7:"
|
||||||
"ssh win7 ./%s.com"))
|
"ssh win7 ./%s.com"))
|
||||||
mode name (file-name-nondirectory name)))
|
mode name (file-name-nondirectory name)))
|
||||||
|
@ -209,7 +209,7 @@
|
||||||
(cosmo-join
|
(cosmo-join
|
||||||
" && "
|
" && "
|
||||||
`("m=%s; f=o/$m/%s.com"
|
`("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:"
|
"scp $f $f.dbg win10:"
|
||||||
"ssh win10 ./%s.com"))
|
"ssh win10 ./%s.com"))
|
||||||
mode name (file-name-nondirectory name)))
|
mode name (file-name-nondirectory name)))
|
||||||
|
@ -218,19 +218,19 @@
|
||||||
(cosmo-join
|
(cosmo-join
|
||||||
" && "
|
" && "
|
||||||
`("m=%s; f=o/$m/%s.com"
|
`("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:"
|
"scp $f $f.dbg xnu:"
|
||||||
"ssh xnu ./%s.com"))
|
"ssh xnu ./%s.com"))
|
||||||
mode name (file-name-nondirectory name)))
|
mode name (file-name-nondirectory name)))
|
||||||
((and (equal suffix "")
|
((and (equal suffix "")
|
||||||
(cosmo-contains "_test." (buffer-file-name)))
|
(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))
|
mode runs))
|
||||||
((and (equal suffix "")
|
((and (equal suffix "")
|
||||||
(file-exists-p (format "%s" buddy)))
|
(file-exists-p (format "%s" buddy)))
|
||||||
(format (cosmo-join
|
(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"
|
;; "bloat o/$m/%s.o | head"
|
||||||
;; "nm -C --size o/$m/%s.o | sort -r"
|
;; "nm -C --size o/$m/%s.o | sort -r"
|
||||||
"echo"
|
"echo"
|
||||||
|
@ -242,11 +242,11 @@
|
||||||
(cosmo-join
|
(cosmo-join
|
||||||
" && "
|
" && "
|
||||||
`("m=%s; f=o/$m/%s.com"
|
`("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"))
|
"./$f"))
|
||||||
mode name))
|
mode name))
|
||||||
((eq kind 'test)
|
((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)
|
((and (file-regular-p this)
|
||||||
(file-executable-p this))
|
(file-executable-p this))
|
||||||
(format "./%s" file))
|
(format "./%s" file))
|
||||||
|
@ -255,7 +255,7 @@
|
||||||
(cosmo-join
|
(cosmo-join
|
||||||
" && "
|
" && "
|
||||||
`("m=%s; f=o/$m/%s%s.o"
|
`("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"
|
;; "nm -C --size $f | sort -r"
|
||||||
"echo"
|
"echo"
|
||||||
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
|
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
|
||||||
|
@ -626,11 +626,11 @@
|
||||||
((eq major-mode 'lua-mode)
|
((eq major-mode 'lua-mode)
|
||||||
(let* ((mode (cosmo--make-mode arg))
|
(let* ((mode (cosmo--make-mode arg))
|
||||||
(redbean ))
|
(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)
|
((and (eq major-mode 'python-mode)
|
||||||
(cosmo-startswith "third_party/python/Lib/test/" file))
|
(cosmo-startswith "third_party/python/Lib/test/" file))
|
||||||
(let ((mode (cosmo--make-mode arg)))
|
(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)))))
|
mode mode (file-name-sans-extension file)))))
|
||||||
((eq major-mode 'python-mode)
|
((eq major-mode 'python-mode)
|
||||||
(compile (format "python.com %s" file)))
|
(compile (format "python.com %s" file)))
|
||||||
|
|
Loading…
Reference in a new issue