mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 07:18:30 +00:00
Fix bugs and make improvements
- Get clone() working on FreeBSD - Increase some Python build quotas - Add more atomic builtins to chibicc - Fix ASAN poisoning of alloca() memory - Make MODE= mandatory link path tinier - Improve the examples folder a little bit - Start working on some more resource limits - Make the linenoise auto-complete UI as good as GNU readline - Update compile.com, avoiding AVX codegen on non-AVX systems - Make sure empty path to syscalls like opendir raises ENOENT - Correctly polyfill ENOENT vs. ENOTDIR on the New Technology - Port bestline's paredit features to //third_party/linenoise - Remove workarounds for RHEL 5.0 bugs that were fixed in 5.1
This commit is contained in:
parent
c3fb624647
commit
ae638c0850
181 changed files with 2994 additions and 1367 deletions
|
@ -40,6 +40,7 @@
|
|||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/kcpuids.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
|
@ -841,6 +842,12 @@ int main(int argc, char *argv[]) {
|
|||
if (isclang && IsGccOnlyFlag(argv[i])) {
|
||||
continue;
|
||||
}
|
||||
if (!X86_HAVE(AVX) &&
|
||||
(!strcmp(argv[i], "-msse2avx") || !strcmp(argv[i], "-Wa,-msse2avx"))) {
|
||||
// Avoid any chance of people using Intel's older or low power
|
||||
// CPUs encountering a SIGILL error due to these awesome flags
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-w")) {
|
||||
AddArg(argv[i]);
|
||||
AddArg("-D__W__");
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#include "tool/build/lib/psk.h"
|
||||
#include "tool/build/runit.h"
|
||||
|
||||
#define MAX_WAIT_CONNECT_SECONDS 30
|
||||
#define MAX_WAIT_CONNECT_SECONDS 12
|
||||
#define INITIAL_CONNECT_TIMEOUT 100000
|
||||
|
||||
/**
|
||||
|
@ -170,81 +170,70 @@ void DeployEphemeralRunItDaemonRemotelyViaSsh(struct addrinfo *ai) {
|
|||
char *args[7];
|
||||
struct stat st;
|
||||
char linebuf[32];
|
||||
struct timeval now, then;
|
||||
sigset_t chldmask, savemask;
|
||||
int sshpid, wstatus, binfd, pipefds[2][2];
|
||||
struct sigaction ignore, saveint, savequit;
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
sigaction(SIGINT, &ignore, &saveint);
|
||||
sigaction(SIGQUIT, &ignore, &savequit);
|
||||
mkdir("o", 0755);
|
||||
CHECK_NE(-1, (lock = open(gc(xasprintf("o/lock.%s", g_hostname)),
|
||||
O_RDWR | O_CREAT, 0644)));
|
||||
CHECK_NE(-1, fcntl(lock, F_SETLKW, &(struct flock){F_WRLCK}));
|
||||
CHECK_NE(-1, gettimeofday(&now, 0));
|
||||
if (!read(lock, &then, 16) || ((now.tv_sec * 1000 + now.tv_usec / 1000) -
|
||||
(then.tv_sec * 1000 + then.tv_usec / 1000)) >=
|
||||
(RUNITD_TIMEOUT_MS >> 1)) {
|
||||
DEBUGF("ssh %s:%hu to spawn %s", g_hostname, g_runitdport, g_runitd);
|
||||
CHECK_NE(-1, (binfd = open(g_runitd, O_RDONLY | O_CLOEXEC)));
|
||||
CHECK_NE(-1, fstat(binfd, &st));
|
||||
args[0] = "ssh";
|
||||
args[1] = "-C";
|
||||
args[2] = "-p";
|
||||
args[3] = gc(xasprintf("%hu", g_sshport));
|
||||
args[4] = g_hostname;
|
||||
args[5] = gc(MakeDeployScript(ai, st.st_size));
|
||||
args[6] = NULL;
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
LOGIFNEG1(sigemptyset(&ignore.sa_mask));
|
||||
LOGIFNEG1(sigaction(SIGINT, &ignore, &saveint));
|
||||
LOGIFNEG1(sigaction(SIGQUIT, &ignore, &savequit));
|
||||
LOGIFNEG1(sigemptyset(&chldmask));
|
||||
LOGIFNEG1(sigaddset(&chldmask, SIGCHLD));
|
||||
LOGIFNEG1(sigprocmask(SIG_BLOCK, &chldmask, &savemask));
|
||||
CHECK_NE(-1, pipe2(pipefds[0], O_CLOEXEC));
|
||||
CHECK_NE(-1, pipe2(pipefds[1], O_CLOEXEC));
|
||||
CHECK_NE(-1, (sshpid = fork()));
|
||||
if (!sshpid) {
|
||||
sigaction(SIGINT, &saveint, NULL);
|
||||
sigaction(SIGQUIT, &savequit, NULL);
|
||||
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||||
dup2(pipefds[0][0], 0);
|
||||
dup2(pipefds[1][1], 1);
|
||||
execv(g_ssh, args);
|
||||
_exit(127);
|
||||
}
|
||||
LOGIFNEG1(close(pipefds[0][0]));
|
||||
LOGIFNEG1(close(pipefds[1][1]));
|
||||
Upload(pipefds[0][1], binfd, &st);
|
||||
LOGIFNEG1(close(pipefds[0][1]));
|
||||
CHECK_NE(-1, (got = read(pipefds[1][0], linebuf, sizeof(linebuf))));
|
||||
CHECK_GT(got, 0, "on host %s", g_hostname);
|
||||
linebuf[sizeof(linebuf) - 1] = '\0';
|
||||
if (strncmp(linebuf, "ready ", 6) != 0) {
|
||||
FATALF("expected ready response but got %`'.*s", got, linebuf);
|
||||
} else {
|
||||
DEBUGF("got ready response");
|
||||
}
|
||||
g_runitdport = (uint16_t)atoi(&linebuf[6]);
|
||||
LOGIFNEG1(close(pipefds[1][0]));
|
||||
CHECK_NE(-1, waitpid(sshpid, &wstatus, 0));
|
||||
LOGIFNEG1(sigaction(SIGINT, &saveint, NULL));
|
||||
LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL));
|
||||
LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL));
|
||||
if (WIFEXITED(wstatus)) {
|
||||
DEBUGF("ssh %s exited with %d", g_hostname, WEXITSTATUS(wstatus));
|
||||
} else {
|
||||
DEBUGF("ssh %s terminated with %s", g_hostname,
|
||||
strsignal(WTERMSIG(wstatus)));
|
||||
}
|
||||
CHECK(WIFEXITED(wstatus) && !WEXITSTATUS(wstatus), "wstatus=%#x", wstatus);
|
||||
CHECK_NE(-1, gettimeofday(&now, 0));
|
||||
CHECK_NE(-1, lseek(lock, 0, SEEK_SET));
|
||||
CHECK_NE(-1, write(lock, &now, 16));
|
||||
} else {
|
||||
DEBUGF("nospawn %s on %s:%hu", g_runitd, g_hostname, g_runitdport);
|
||||
DEBUGF("ssh %s:%hu to spawn %s", g_hostname, g_runitdport, g_runitd);
|
||||
CHECK_NE(-1, (binfd = open(g_runitd, O_RDONLY | O_CLOEXEC)));
|
||||
CHECK_NE(-1, fstat(binfd, &st));
|
||||
args[0] = "ssh";
|
||||
args[1] = "-C";
|
||||
args[2] = "-p";
|
||||
args[3] = gc(xasprintf("%hu", g_sshport));
|
||||
args[4] = g_hostname;
|
||||
args[5] = gc(MakeDeployScript(ai, st.st_size));
|
||||
args[6] = NULL;
|
||||
sigemptyset(&chldmask);
|
||||
sigaddset(&chldmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
|
||||
CHECK_NE(-1, pipe2(pipefds[0], O_CLOEXEC));
|
||||
CHECK_NE(-1, pipe2(pipefds[1], O_CLOEXEC));
|
||||
CHECK_NE(-1, (sshpid = fork()));
|
||||
if (!sshpid) {
|
||||
sigaction(SIGINT, &(struct sigaction){0}, 0);
|
||||
sigaction(SIGQUIT, &(struct sigaction){0}, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
dup2(pipefds[0][0], 0);
|
||||
dup2(pipefds[1][1], 1);
|
||||
execv(g_ssh, args);
|
||||
_exit(127);
|
||||
}
|
||||
CHECK_NE(-1, fcntl(lock, F_SETLK, &(struct flock){F_UNLCK}));
|
||||
LOGIFNEG1(close(lock));
|
||||
close(pipefds[0][0]);
|
||||
close(pipefds[1][1]);
|
||||
Upload(pipefds[0][1], binfd, &st);
|
||||
LOGIFNEG1(close(pipefds[0][1]));
|
||||
CHECK_NE(-1, (got = read(pipefds[1][0], linebuf, sizeof(linebuf))));
|
||||
CHECK_GT(got, 0, "on host %s", g_hostname);
|
||||
linebuf[sizeof(linebuf) - 1] = '\0';
|
||||
if (strncmp(linebuf, "ready ", 6) != 0) {
|
||||
FATALF("expected ready response but got %`'.*s", got, linebuf);
|
||||
} else {
|
||||
DEBUGF("got ready response");
|
||||
}
|
||||
g_runitdport = (uint16_t)atoi(&linebuf[6]);
|
||||
LOGIFNEG1(close(pipefds[1][0]));
|
||||
CHECK_NE(-1, waitpid(sshpid, &wstatus, 0));
|
||||
LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL));
|
||||
if (WIFEXITED(wstatus)) {
|
||||
DEBUGF("ssh %s exited with %d", g_hostname, WEXITSTATUS(wstatus));
|
||||
} else {
|
||||
DEBUGF("ssh %s terminated with %s", g_hostname,
|
||||
strsignal(WTERMSIG(wstatus)));
|
||||
}
|
||||
CHECK(WIFEXITED(wstatus) && !WEXITSTATUS(wstatus), "wstatus=%#x", wstatus);
|
||||
LOGIFNEG1(fcntl(lock, F_SETLK, &(struct flock){F_UNLCK}));
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
close(lock);
|
||||
}
|
||||
|
||||
void Connect(void) {
|
||||
|
@ -454,21 +443,21 @@ int SpawnSubprocesses(int argc, char *argv[]) {
|
|||
pids = calloc(argc, sizeof(int));
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
LOGIFNEG1(sigemptyset(&ignore.sa_mask));
|
||||
LOGIFNEG1(sigaction(SIGINT, &ignore, &saveint));
|
||||
LOGIFNEG1(sigaction(SIGQUIT, &ignore, &savequit));
|
||||
LOGIFNEG1(sigemptyset(&chldmask));
|
||||
LOGIFNEG1(sigaddset(&chldmask, SIGCHLD));
|
||||
LOGIFNEG1(sigprocmask(SIG_BLOCK, &chldmask, &savemask));
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
sigaction(SIGINT, &ignore, &saveint);
|
||||
sigaction(SIGQUIT, &ignore, &savequit);
|
||||
sigemptyset(&chldmask);
|
||||
sigaddset(&chldmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
|
||||
for (i = 0; i < argc; ++i) {
|
||||
args[3] = argv[i];
|
||||
CHECK_NE(-1, (pids[i] = vfork()));
|
||||
if (!pids[i]) {
|
||||
xsigaction(SIGINT, SIG_DFL, 0, 0, 0);
|
||||
xsigaction(SIGQUIT, SIG_DFL, 0, 0, 0);
|
||||
sigaction(SIGINT, &(struct sigaction){0}, 0);
|
||||
sigaction(SIGQUIT, &(struct sigaction){0}, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
execve(args[0], args, environ); /* for htop */
|
||||
_exit(127);
|
||||
_Exit(127);
|
||||
}
|
||||
}
|
||||
for (exitcode = 0;;) {
|
||||
|
@ -493,9 +482,9 @@ int SpawnSubprocesses(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
LOGIFNEG1(sigaction(SIGINT, &saveint, NULL));
|
||||
LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL));
|
||||
LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL));
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
free(pids);
|
||||
return exitcode;
|
||||
}
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -98,7 +100,7 @@ char *g_exepath;
|
|||
volatile bool g_interrupted;
|
||||
struct sockaddr_in g_servaddr;
|
||||
unsigned char g_buf[PAGESIZE];
|
||||
bool g_daemonize, g_sendready, g_alarmed;
|
||||
bool g_daemonize, g_sendready;
|
||||
int g_timeout, g_bogusfd, g_servfd, g_clifd, g_exefd;
|
||||
|
||||
void OnInterrupt(int sig) {
|
||||
|
@ -254,18 +256,6 @@ void SendOutputFragmentMessage(enum RunitCommand kind, unsigned char *buf,
|
|||
CHECK_EQ(0, EzTlsFlush(&ezbio, 0, 0));
|
||||
}
|
||||
|
||||
void OnAlarm(int sig) {
|
||||
g_alarmed = true;
|
||||
}
|
||||
|
||||
void SetDeadline(int seconds, int micros) {
|
||||
g_alarmed = false;
|
||||
LOGIFNEG1(
|
||||
sigaction(SIGALRM, &(struct sigaction){.sa_handler = OnAlarm}, NULL));
|
||||
LOGIFNEG1(setitimer(
|
||||
ITIMER_REAL, &(const struct itimerval){{0, 0}, {seconds, micros}}, NULL));
|
||||
}
|
||||
|
||||
void Recv(void *p, size_t n) {
|
||||
size_t i, rc;
|
||||
for (i = 0; i < n; i += rc) {
|
||||
|
@ -284,12 +274,13 @@ void HandleClient(void) {
|
|||
uint32_t crc;
|
||||
ssize_t got, wrote;
|
||||
struct sockaddr_in addr;
|
||||
long double now, deadline;
|
||||
sigset_t chldmask, savemask;
|
||||
char *addrstr, *exename, *exe;
|
||||
unsigned char msg[4 + 1 + 4 + 4 + 4];
|
||||
struct sigaction ignore, saveint, savequit;
|
||||
int rc, exitcode, wstatus, child, pipefds[2];
|
||||
uint32_t addrsize, namesize, filesize, remaining;
|
||||
int rc, events, exitcode, wstatus, child, pipefds[2];
|
||||
|
||||
/* read request to run program */
|
||||
addrsize = sizeof(addr);
|
||||
|
@ -326,80 +317,87 @@ void HandleClient(void) {
|
|||
|
||||
/* run program, tee'ing stderr to both log and client */
|
||||
DEBUGF("spawning %s", exename);
|
||||
SetDeadline(DEATH_CLOCK_SECONDS, 0);
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
LOGIFNEG1(sigemptyset(&ignore.sa_mask));
|
||||
LOGIFNEG1(sigaction(SIGINT, &ignore, &saveint));
|
||||
LOGIFNEG1(sigaction(SIGQUIT, &ignore, &savequit));
|
||||
LOGIFNEG1(sigemptyset(&chldmask));
|
||||
LOGIFNEG1(sigaddset(&chldmask, SIGCHLD));
|
||||
LOGIFNEG1(sigprocmask(SIG_BLOCK, &chldmask, &savemask));
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
sigaction(SIGINT, &ignore, &saveint);
|
||||
sigaction(SIGQUIT, &ignore, &savequit);
|
||||
sigemptyset(&chldmask);
|
||||
sigaddset(&chldmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
|
||||
CHECK_NE(-1, pipe2(pipefds, O_CLOEXEC));
|
||||
CHECK_NE(-1, (child = fork()));
|
||||
if (!child) {
|
||||
sigaction(SIGINT, &saveint, NULL);
|
||||
sigaction(SIGQUIT, &savequit, NULL);
|
||||
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||||
/* dup2(g_bogusfd, 0); */
|
||||
dup2(g_bogusfd, 0);
|
||||
dup2(pipefds[1], 1);
|
||||
dup2(pipefds[1], 2);
|
||||
if (pipefds[0] > 2) close(pipefds[1]);
|
||||
if (g_bogusfd > 2) close(g_bogusfd);
|
||||
sigaction(SIGINT, &(struct sigaction){0}, 0);
|
||||
sigaction(SIGQUIT, &(struct sigaction){0}, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
int i = 0;
|
||||
char *args[4] = {0};
|
||||
args[i++] = g_exepath;
|
||||
if (use_strace) args[i++] = "--strace";
|
||||
if (use_ftrace) args[i++] = "--ftrace";
|
||||
execv(g_exepath, args);
|
||||
_exit(127);
|
||||
_Exit(127);
|
||||
}
|
||||
LOGIFNEG1(close(pipefds[1]));
|
||||
close(pipefds[1]);
|
||||
DEBUGF("communicating %s[%d]", exename, child);
|
||||
while (!g_alarmed) {
|
||||
got = read(pipefds[0], g_buf, sizeof(g_buf));
|
||||
if (got != -1) {
|
||||
if (!got) {
|
||||
close(pipefds[0]);
|
||||
break;
|
||||
}
|
||||
fwrite(g_buf, got, 1, stderr);
|
||||
SendOutputFragmentMessage(kRunitStderr, g_buf, got);
|
||||
} else {
|
||||
CHECK_EQ(EINTR, errno);
|
||||
}
|
||||
}
|
||||
deadline = nowl() + DEATH_CLOCK_SECONDS;
|
||||
for (;;) {
|
||||
if (g_alarmed) {
|
||||
WARNF("killing %s which timed out");
|
||||
LOGIFNEG1(kill(child, SIGKILL));
|
||||
g_alarmed = false;
|
||||
now = nowl();
|
||||
if (now >= deadline) {
|
||||
WARNF("%s worker timed out", exename);
|
||||
LOGIFNEG1(kill(child, 9));
|
||||
LOGIFNEG1(waitpid(child, 0, 0));
|
||||
LOGIFNEG1(close(g_clifd));
|
||||
LOGIFNEG1(close(pipefds[0]));
|
||||
LOGIFNEG1(unlink(g_exepath));
|
||||
_exit(1);
|
||||
}
|
||||
if (waitpid(child, &wstatus, 0) != -1) {
|
||||
struct pollfd fds[2];
|
||||
fds[0].fd = g_clifd;
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = pipefds[0];
|
||||
fds[1].events = POLLIN;
|
||||
events = poll(fds, ARRAYLEN(fds), (deadline - now) * 1000);
|
||||
CHECK_NE(-1, events); // EINTR shouldn't be possible
|
||||
if (fds[0].revents) {
|
||||
if (!(fds[0].revents & POLLHUP)) {
|
||||
WARNF("%s got unexpected input event from client %#x", exename,
|
||||
fds[0].revents);
|
||||
}
|
||||
WARNF("%s client disconnected so killing worker", exename);
|
||||
LOGIFNEG1(kill(child, 9));
|
||||
LOGIFNEG1(waitpid(child, 0, 0));
|
||||
LOGIFNEG1(close(g_clifd));
|
||||
LOGIFNEG1(close(pipefds[0]));
|
||||
LOGIFNEG1(unlink(g_exepath));
|
||||
_exit(1);
|
||||
}
|
||||
got = read(pipefds[0], g_buf, sizeof(g_buf));
|
||||
CHECK_NE(-1, got); // EINTR shouldn't be possible
|
||||
if (!got) {
|
||||
LOGIFNEG1(close(pipefds[0]));
|
||||
break;
|
||||
} else {
|
||||
CHECK_EQ(EINTR, errno);
|
||||
}
|
||||
fwrite(g_buf, got, 1, stderr);
|
||||
SendOutputFragmentMessage(kRunitStderr, g_buf, got);
|
||||
}
|
||||
CHECK_NE(-1, waitpid(child, &wstatus, 0)); // EINTR shouldn't be possible
|
||||
if (WIFEXITED(wstatus)) {
|
||||
if (WEXITSTATUS(wstatus)) {
|
||||
WARNF("%s exited with %d", exename, WEXITSTATUS(wstatus));
|
||||
} else {
|
||||
DEBUGF("%s exited with %d", exename, WEXITSTATUS(wstatus));
|
||||
VERBOSEF("%s exited with %d", exename, WEXITSTATUS(wstatus));
|
||||
}
|
||||
exitcode = WEXITSTATUS(wstatus);
|
||||
} else {
|
||||
WARNF("%s terminated with %s", exename, strsignal(WTERMSIG(wstatus)));
|
||||
exitcode = 128 + WTERMSIG(wstatus);
|
||||
}
|
||||
LOGIFNEG1(sigaction(SIGINT, &saveint, NULL));
|
||||
LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL));
|
||||
LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL));
|
||||
|
||||
/* let client know how it went */
|
||||
if (unlink(g_exepath) == -1) {
|
||||
WARNF("failed to delete executable %`'s", g_exepath);
|
||||
}
|
||||
LOGIFNEG1(unlink(g_exepath));
|
||||
SendExitMessage(exitcode);
|
||||
mbedtls_ssl_close_notify(&ezssl);
|
||||
LOGIFNEG1(close(g_clifd));
|
||||
|
@ -429,12 +427,11 @@ TryAgain:
|
|||
|
||||
int Serve(void) {
|
||||
StartTcpServer();
|
||||
sigaction(SIGINT, (&(struct sigaction){.sa_handler = (void *)OnInterrupt}),
|
||||
NULL);
|
||||
sigaction(SIGINT, (&(struct sigaction){.sa_handler = OnInterrupt}), 0);
|
||||
sigaction(SIGCHLD,
|
||||
(&(struct sigaction){.sa_handler = (void *)OnChildTerminated,
|
||||
(&(struct sigaction){.sa_handler = OnChildTerminated,
|
||||
.sa_flags = SA_RESTART}),
|
||||
NULL);
|
||||
0);
|
||||
for (;;) {
|
||||
if (!Poll() && (!g_timeout || g_interrupted)) break;
|
||||
}
|
||||
|
@ -461,10 +458,12 @@ void Daemonize(void) {
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
ShowCrashReports();
|
||||
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER, GetRunitPsk());
|
||||
/* __log_level = kLogDebug; */
|
||||
GetOpts(argc, argv);
|
||||
for (i = 3; i < 16; ++i) close(i);
|
||||
// poll()'ing /dev/null stdin file descriptor on xnu returns POLLNVAL?!
|
||||
if (IsWindows()) {
|
||||
CHECK_EQ(3, (g_bogusfd = open("/dev/null", O_RDONLY | O_CLOEXEC)));
|
||||
|
|
|
@ -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; make -j8 -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 "make -j8 -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,19 +209,19 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j8 -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)))
|
||||
((and (equal suffix "")
|
||||
(cosmo-contains "_test." (buffer-file-name)))
|
||||
(format "m=%s; make -j8 -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; make -j8 -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"
|
||||
|
@ -233,11 +233,11 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j8 -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 && make -j8 -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))
|
||||
|
@ -246,7 +246,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s%s.o"
|
||||
,(concat "make -j8 -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"
|
||||
|
@ -456,7 +456,7 @@
|
|||
(error "don't know how to show assembly for non c/c++ source file"))
|
||||
(let* ((default-directory root)
|
||||
(compile-command
|
||||
(format "make %s -j8 -O MODE=%s %s %s"
|
||||
(format "make %s -j12 -O MODE=%s %s %s"
|
||||
(or extra-make-flags "") mode asm-gcc asm-clang)))
|
||||
(save-buffer)
|
||||
(set-visited-file-modtime (current-time))
|
||||
|
@ -613,7 +613,7 @@
|
|||
((and (eq major-mode 'python-mode)
|
||||
(cosmo-startswith "third_party/python/Lib/test/" file))
|
||||
(let ((mode (cosmo--make-mode arg)))
|
||||
(compile (format "make -j8 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)))
|
||||
|
|
|
@ -32,7 +32,31 @@ local function main()
|
|||
|
||||
-- steal client from redbean
|
||||
fd = GetClientFd()
|
||||
rc = unix.fork()
|
||||
rc, errno = unix.fork()
|
||||
|
||||
if errno then
|
||||
SetStatus(400)
|
||||
SetHeader('Content-Type', 'text/html; charset=utf-8')
|
||||
Write('<!doctype html>\r\n')
|
||||
Write('<title>redbean unix module</title>\r\n')
|
||||
Write('<h1>\r\n')
|
||||
Write('<img style="vertical-align:middle" src="data:image/png;base64,\r\n')
|
||||
Write(EncodeBase64(LoadAsset('/redbean.png')))
|
||||
Write('">\r\n')
|
||||
Write('redbean unix demo\r\n')
|
||||
Write(string.format('<span style="color:red"> %s</span>\r\n', unix.strerrno(errno)))
|
||||
Write('</h1>\r\n')
|
||||
Write([[
|
||||
<p>
|
||||
Your redbean doesn't have the ability to fork. Most likely
|
||||
because you enabled sandboxing and fork() isn't in your bpf
|
||||
policy.
|
||||
</p>
|
||||
]])
|
||||
Write('</h1>\r\n')
|
||||
return
|
||||
end
|
||||
|
||||
if rc ~= 0 then
|
||||
unix.close(fd)
|
||||
return
|
||||
|
|
|
@ -1539,9 +1539,13 @@ UNIX MODULE
|
|||
unix.sigaction(unix.SIGALRM, MyOnSigAlrm, unix.SA_RESETHAND)
|
||||
unix.setitimer(unix.ITIMER_REAL, 0, 0, 1, 0)
|
||||
|
||||
unix.strerrno(errno:int) → str
|
||||
|
||||
Turns `errno` code into its symbolic name, e.g. `"EINTR"`.
|
||||
|
||||
unix.strerror(errno:int) → str
|
||||
|
||||
Turns `errno` code into a string describing the error.
|
||||
Turns `errno` code into a longer string describing the error.
|
||||
|
||||
unix.strsignal(sig:int) → str
|
||||
|
||||
|
@ -1776,10 +1780,10 @@ UNIX MODULE
|
|||
in a supplied path *existed* but wasn't a directory. For example,
|
||||
if you try to `open("foo/bar")` and `foo` is a regular file, then
|
||||
`ENOTDIR` will be returned. Raised by open(), access(), chdir(),
|
||||
chmod(), chown(), chroot(), execve(), fcntl(), futimesat(),
|
||||
inotify_add_watch(), link(), mkdir(), mknod(), opendir(),
|
||||
readlink(), rename(), rmdir(), stat(), symlink(), sysctl(),
|
||||
truncate(), unlink(), utimensat(), bind().
|
||||
chroot(), execve(), link(), mkdir(), mknod(), opendir(),
|
||||
readlink(), rename(), rmdir(), stat(), symlink(), truncate(),
|
||||
unlink(), utimensat(), bind(), chmod(), chown(), fcntl(),
|
||||
futimesat(), inotify_add_watch().
|
||||
|
||||
- `EISDIR`: Is a a directory. Raised by copy_file_range(),
|
||||
execve(), open(), read(), rename(), truncate(), unlink().
|
||||
|
|
|
@ -536,6 +536,16 @@ static int LuaUnixSetpgid(lua_State *L) {
|
|||
return ReturnRc(L, rc, olderr);
|
||||
}
|
||||
|
||||
// unix.setpgrp() → pgid:int[, errno:int]
|
||||
static int LuaUnixSetpgrp(lua_State *L) {
|
||||
int rc, pid, pgrp, olderr;
|
||||
olderr = errno;
|
||||
pid = luaL_checkinteger(L, 1);
|
||||
pgrp = luaL_checkinteger(L, 2);
|
||||
rc = setpgrp();
|
||||
return ReturnRc(L, rc, olderr);
|
||||
}
|
||||
|
||||
// unix.setsid() → sid:int[, errno:int]
|
||||
static int LuaUnixSetsid(lua_State *L) {
|
||||
int rc, olderr;
|
||||
|
@ -1231,6 +1241,12 @@ static int LuaUnixStrerror(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// unix.strerrno(errno) → str
|
||||
static int LuaUnixStrerrno(lua_State *L) {
|
||||
lua_pushstring(L, strerror_short(luaL_checkinteger(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// unix.strsignal(sig) → str
|
||||
static int LuaUnixStrsignal(lua_State *L) {
|
||||
lua_pushstring(L, strsignal(luaL_checkinteger(L, 1)));
|
||||
|
@ -1506,6 +1522,7 @@ static const luaL_Reg kLuaUnix[] = {
|
|||
{"getpgrp", LuaUnixGetpgrp}, // get process group id
|
||||
{"getpgid", LuaUnixGetpgid}, // get process group id of pid
|
||||
{"setpgid", LuaUnixSetpgid}, // set process group id for pid
|
||||
{"setpgrp", LuaUnixSetpgrp}, // sets process group id
|
||||
{"getsid", LuaUnixGetsid}, // get session id of pid
|
||||
{"setsid", LuaUnixSetsid}, // create a new session id
|
||||
{"getpid", LuaUnixGetpid}, // get id of this process
|
||||
|
@ -1533,6 +1550,7 @@ static const luaL_Reg kLuaUnix[] = {
|
|||
{"sigsuspend", LuaUnixSigsuspend}, // wait for signal
|
||||
{"setitimer", LuaUnixSetitimer}, // set alarm clock
|
||||
{"strerror", LuaUnixStrerror}, // turn errno into string
|
||||
{"strerrno", LuaUnixStrerrno}, // turn errno into string
|
||||
{"strsignal", LuaUnixStrsignal}, // turn signal into string
|
||||
{0}, //
|
||||
};
|
||||
|
@ -1571,6 +1589,7 @@ int LuaUnix(lua_State *L) {
|
|||
LuaSetIntField(L, "O_EXCL", O_EXCL); //
|
||||
LuaSetIntField(L, "O_TRUNC", O_TRUNC); //
|
||||
LuaSetIntField(L, "O_CLOEXEC", O_CLOEXEC); //
|
||||
LuaSetIntField(L, "O_DIRECT", O_DIRECT); // no-op on xnu/openbsd
|
||||
LuaSetIntField(L, "O_APPEND", O_APPEND); // weird on nt
|
||||
LuaSetIntField(L, "O_TMPFILE", O_TMPFILE); // linux, windows
|
||||
LuaSetIntField(L, "O_NOFOLLOW", O_NOFOLLOW); // unix
|
||||
|
@ -1616,6 +1635,7 @@ int LuaUnix(lua_State *L) {
|
|||
|
||||
// rlimit() resources
|
||||
LuaSetIntField(L, "RLIMIT_AS", RLIMIT_AS);
|
||||
LuaSetIntField(L, "RLIMIT_RSS", RLIMIT_RSS);
|
||||
LuaSetIntField(L, "RLIMIT_CPU", RLIMIT_CPU);
|
||||
LuaSetIntField(L, "RLIMIT_FSIZE", RLIMIT_FSIZE);
|
||||
LuaSetIntField(L, "RLIMIT_NPROC", RLIMIT_NPROC);
|
||||
|
|
|
@ -176,8 +176,8 @@ STATIC_YOINK("zip_uri_support");
|
|||
#define VERSION 0x010500
|
||||
#define HEARTBEAT 5000 /*ms*/
|
||||
#define HASH_LOAD_FACTOR /* 1. / */ 4
|
||||
#define read(F, P, N) readv(F, &(struct iovec){P, N}, 1)
|
||||
#define write(F, P, N) writev(F, &(struct iovec){P, N}, 1)
|
||||
#define READ(F, P, N) readv(F, &(struct iovec){P, N}, 1)
|
||||
#define WRITE(F, P, N) writev(F, &(struct iovec){P, N}, 1)
|
||||
#define LockInc(P) asm volatile("lock incq\t%0" : "=m"(*(P)))
|
||||
#define AppendCrlf(P) mempcpy(P, "\r\n", 2)
|
||||
#define HasHeader(H) (!!msg.headers[H].a)
|
||||
|
@ -1029,7 +1029,7 @@ static void Daemonize(void) {
|
|||
umask(0);
|
||||
if (pidpath) {
|
||||
fd = open(pidpath, O_CREAT | O_WRONLY, 0644);
|
||||
write(fd, ibuf, uint64toarray_radix10(getpid(), ibuf));
|
||||
WRITE(fd, ibuf, uint64toarray_radix10(getpid(), ibuf));
|
||||
close(fd);
|
||||
}
|
||||
if (!logpath) ProgramLogPath("/dev/null");
|
||||
|
@ -1253,7 +1253,7 @@ static ssize_t ReadAll(int fd, char *p, size_t n) {
|
|||
ssize_t rc;
|
||||
size_t i, got;
|
||||
for (i = 0; i < n;) {
|
||||
rc = read(fd, p + i, n - i);
|
||||
rc = READ(fd, p + i, n - i);
|
||||
if (rc != -1) {
|
||||
got = rc;
|
||||
i += got;
|
||||
|
@ -2727,7 +2727,7 @@ static void LaunchBrowser(const char *path) {
|
|||
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
|
||||
CHECK_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
setpgid(getpid(), getpid()); // ctrl-c'ing redbean shouldn't kill browser
|
||||
setpgrp(); // ctrl-c'ing redbean shouldn't kill browser
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
|
@ -3396,13 +3396,10 @@ static void StoreAsset(char *path, size_t pathlen, char *data, size_t datalen,
|
|||
uint16_t gflags, iattrs, mtime, mdate, dosmode, method, disk;
|
||||
size_t oldcdirsize, oldcdiroffset, records, cdiroffset, cdirsize, complen,
|
||||
uselen;
|
||||
|
||||
if (IsOpenbsd() || IsNetbsd() || IsWindows()) {
|
||||
DIEF("(cfg) StoreAsset() not available on Windows/NetBSD/OpenBSD yet");
|
||||
}
|
||||
|
||||
INFOF("Storing asset %`'s", path);
|
||||
|
||||
disk = gflags = iattrs = 0;
|
||||
if (_isutf8(path, pathlen)) gflags |= kZipGflagUtf8;
|
||||
if (_istext(data, datalen)) iattrs |= kZipIattrText;
|
||||
|
@ -3870,7 +3867,7 @@ static int LuaFetch(lua_State *L) {
|
|||
LuaThrowTlsError(L, "write", ret);
|
||||
unreachable;
|
||||
}
|
||||
} else if (write(sock, request, requestlen) != requestlen) {
|
||||
} else if (WRITE(sock, request, requestlen) != requestlen) {
|
||||
close(sock);
|
||||
luaL_error(L, "write error: %s", strerror(errno));
|
||||
unreachable;
|
||||
|
@ -3904,7 +3901,7 @@ static int LuaFetch(lua_State *L) {
|
|||
unreachable;
|
||||
}
|
||||
}
|
||||
} else if ((rc = read(sock, inbuf.p + inbuf.n, inbuf.c - inbuf.n)) == -1) {
|
||||
} else if ((rc = READ(sock, inbuf.p + inbuf.n, inbuf.c - inbuf.n)) == -1) {
|
||||
close(sock);
|
||||
free(inbuf.p);
|
||||
DestroyHttpMessage(&msg);
|
||||
|
@ -6863,7 +6860,7 @@ static void RestoreApe(void) {
|
|||
if (endswith(zpath, ".com.dbg")) return;
|
||||
if ((a = GetAssetZip("/.ape", 5)) && (p = LoadAsset(a, &n))) {
|
||||
close(zfd);
|
||||
if ((zfd = OpenExecutable()) == -1 || write(zfd, p, n) == -1)
|
||||
if ((zfd = OpenExecutable()) == -1 || WRITE(zfd, p, n) == -1)
|
||||
WARNF("(srvr) can't restore .ape");
|
||||
free(p);
|
||||
} else {
|
||||
|
@ -7197,7 +7194,7 @@ void RedBean(int argc, char *argv[]) {
|
|||
// ctrl-c isn't propagating as expected when running redbean
|
||||
// underneath strace.com :|
|
||||
if (!IsWindows()) {
|
||||
setpgid(getpid(), getpid());
|
||||
setpgrp();
|
||||
}
|
||||
if (logpath) {
|
||||
close(2);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue