Fix bugs with recent change

This change makes further effort towards improving our poll()
implementation on the New Technology. The stdin worker didn't work out
so well for Python so it's not being used for now. System call tracing
with the --strace flag should now be less noisy now on Windows unless
you modify the strace.internal.h defines to turn on some optional ones
that are most useful for debugging the system call wrappers.
This commit is contained in:
Justine Tunney 2022-04-16 10:40:23 -07:00
parent 933411ba99
commit dc0ea6640e
127 changed files with 1354 additions and 866 deletions

View file

@ -99,7 +99,7 @@ volatile bool g_interrupted;
struct sockaddr_in g_servaddr;
unsigned char g_buf[PAGESIZE];
bool g_daemonize, g_sendready, g_alarmed;
int g_timeout, g_devnullfd, g_servfd, g_clifd, g_exefd;
int g_timeout, g_bogusfd, g_servfd, g_clifd, g_exefd;
void OnInterrupt(int sig) {
g_interrupted = true;
@ -193,10 +193,8 @@ void StartTcpServer(void) {
* TODO: How can we make close(serversocket) on Windows go fast?
* That way we can put back SOCK_CLOEXEC.
*/
CHECK_NE(-1, (g_servfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)));
CHECK_NE(-1, dup2(g_servfd, 10));
CHECK_NE(-1, close(g_servfd));
g_servfd = 10;
CHECK_NE(-1, (g_servfd =
socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP)));
LOGIFNEG1(setsockopt(g_servfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)));
if (bind(g_servfd, &g_servaddr, sizeof(g_servaddr)) == -1) {
@ -216,7 +214,7 @@ void StartTcpServer(void) {
printf("ready %hu\n", ntohs(g_servaddr.sin_port));
fflush(stdout);
fclose(stdout);
dup2(g_devnullfd, stdout->fd);
dup2(g_bogusfd, stdout->fd);
}
}
@ -343,11 +341,11 @@ void HandleClient(void) {
sigaction(SIGINT, &saveint, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &savemask, NULL);
dup2(g_devnullfd, 0);
/* dup2(g_bogusfd, 0); */
dup2(pipefds[1], 1);
dup2(pipefds[1], 2);
if (pipefds[0] > 2) close(pipefds[1]);
if (g_devnullfd > 2) close(g_devnullfd);
if (g_bogusfd > 2) close(g_bogusfd);
int i = 0;
char *args[4] = {0};
args[i++] = g_exepath;
@ -454,8 +452,8 @@ void Daemonize(void) {
if (fork() > 0) _exit(0);
setsid();
if (fork() > 0) _exit(0);
dup2(g_devnullfd, stdin->fd);
if (!g_sendready) dup2(g_devnullfd, stdout->fd);
dup2(g_bogusfd, stdin->fd);
if (!g_sendready) dup2(g_bogusfd, stdout->fd);
freopen(kLogFile, "ae", stderr);
if (fstat(fileno(stderr), &st) != -1 && st.st_size > kLogMaxBytes) {
ftruncate(fileno(stderr), 0);
@ -467,8 +465,13 @@ int main(int argc, char *argv[]) {
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER, GetRunitPsk());
/* __log_level = kLogDebug; */
GetOpts(argc, argv);
CHECK_EQ(3, (g_devnullfd = open("/dev/null", O_RDWR | O_CLOEXEC)));
defer(close_s, &g_devnullfd);
// 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)));
} else {
CHECK_EQ(3, (g_bogusfd = open("/dev/zero", O_RDONLY | O_CLOEXEC)));
}
defer(close_s, &g_bogusfd);
if (!isdirectory("o")) CHECK_NE(-1, mkdir("o", 0700));
if (g_daemonize) Daemonize();
return Serve();

View file

@ -22,6 +22,7 @@
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/user_regs_struct.h"
@ -1042,11 +1043,12 @@ wontreturn void PropagateTermination(int wstatus) {
wontreturn void StraceMain(int argc, char *argv[]) {
unsigned long msg;
struct siginfo si;
struct Pid *s, *child;
struct PidList pidlist;
sigset_t mask, truemask;
struct sigaction sigdfl;
sigset_t mask, origmask;
int i, sig, evpid, root, wstatus, signal;
struct sigaction sigign, saveint, savequit;
if (!IsLinux()) {
kprintf("error: ptrace() is only supported on linux right now%n");
@ -1064,20 +1066,22 @@ wontreturn void StraceMain(int argc, char *argv[]) {
pidlist.n = 0;
pidlist.p = 0;
sigdfl.sa_flags = 0;
sigdfl.sa_handler = SIG_DFL;
sigemptyset(&sigdfl.sa_mask);
sigign.sa_flags = 0;
sigign.sa_handler = SIG_IGN;
sigemptyset(&sigign.sa_mask);
sigaction(SIGINT, &sigign, &saveint);
sigaction(SIGQUIT, &sigign, &savequit);
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGTERM);
sigprocmask(SIG_BLOCK, &mask, &truemask);
/* sigaddset(&mask, SIGCHLD); */
sigprocmask(SIG_BLOCK, &mask, &origmask);
CHECK_NE(-1, (root = vfork()));
CHECK_NE(-1, (root = fork()));
if (!root) {
sigprocmask(SIG_SETMASK, &truemask, 0);
sigaction(SIGINT, &saveint, 0);
sigaction(SIGQUIT, &savequit, 0);
sigprocmask(SIG_SETMASK, &origmask, 0);
ptrace(PTRACE_TRACEME);
execvp(argv[1], argv + 1);
_Exit(127);
@ -1091,7 +1095,7 @@ wontreturn void StraceMain(int argc, char *argv[]) {
CHECK_NE(-1, ptrace(PTRACE_SETOPTIONS, sp->pid, 0,
(PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK |
PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC |
PTRACE_O_TRACEEXIT)));
PTRACE_O_TRACEEXIT | PTRACE_O_TRACESYSGOOD)));
// continue child process setting breakpoint at next system call
CHECK_NE(-1, ptrace(PTRACE_SYSCALL, sp->pid, 0, 0));
@ -1120,8 +1124,20 @@ wontreturn void StraceMain(int argc, char *argv[]) {
// handle actual kill
if (WIFSIGNALED(wstatus)) {
kprintf(PROLOGUE " exited with signal %s%n", sp->pid,
strsignal(WTERMSIG(wstatus)));
kprintf(PROLOGUE " exited with signal %G%n", sp->pid, WTERMSIG(wstatus));
RemovePid(&pidlist, sp->pid);
sp = 0;
// we die when the last process being monitored dies
if (!pidlist.i) {
PropagateTermination(wstatus);
} else {
continue;
}
}
// handle core dump
if (WCOREDUMP(wstatus)) {
kprintf(PROLOGUE " exited with core%n", sp->pid);
RemovePid(&pidlist, sp->pid);
sp = 0;
// we die when the last process being monitored dies
@ -1136,19 +1152,29 @@ wontreturn void StraceMain(int argc, char *argv[]) {
sig = 0;
signal = (wstatus >> 8) & 0xffff;
assert(WIFSTOPPED(wstatus));
if (signal == SIGTRAP) {
CHECK_NE(-1, ptrace(PTRACE_GETREGS, sp->pid, 0, &sp->args));
PrintSyscall(sp->insyscall);
sp->insyscall = !sp->insyscall;
if (signal == SIGTRAP | PTRACE_EVENT_STOP) {
CHECK_NE(-1, ptrace(PTRACE_GETSIGINFO, sp->pid, 0, &si));
if (si.si_code == SIGTRAP || si.si_code == SIGTRAP | 0x80) {
CHECK_NE(-1, ptrace(PTRACE_GETREGS, sp->pid, 0, &sp->args));
PrintSyscall(sp->insyscall);
sp->insyscall = !sp->insyscall;
ptrace(PTRACE_SYSCALL, sp->pid, 0, 0);
} else {
sig = signal & 127;
kappendf(&ob, PROLOGUE " got signal %G%n", sp->pid, sig);
Flush();
ptrace(PTRACE_SYSCALL, sp->pid, 0, sig);
}
} else if (signal == (SIGTRAP | (PTRACE_EVENT_EXIT << 8))) {
CHECK_NE(-1, ptrace(PTRACE_GETEVENTMSG, sp->pid, 0, &msg));
sig = WSTOPSIG(wstatus);
ptrace(PTRACE_SYSCALL, sp->pid, 0, 0);
} else if (signal == (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) {
CHECK_NE(-1, ptrace(PTRACE_GETEVENTMSG, sp->pid, 0, &msg));
} else if (WIFSTOPPED(wstatus) &&
(signal == (SIGTRAP | (PTRACE_EVENT_FORK << 8)) ||
signal == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)) ||
signal == (SIGTRAP | (PTRACE_EVENT_CLONE << 8)))) {
ptrace(PTRACE_SYSCALL, sp->pid, 0, 0);
} else if (signal == (SIGTRAP | (PTRACE_EVENT_FORK << 8)) ||
signal == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)) ||
signal == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
CHECK_NE(-1, ptrace(PTRACE_GETEVENTMSG, evpid, 0, &msg));
child = AddPid(&pidlist, msg);
child->pid = msg;
@ -1161,18 +1187,12 @@ wontreturn void StraceMain(int argc, char *argv[]) {
}
Flush();
ptrace(PTRACE_SYSCALL, child->pid, 0, 0);
ptrace(PTRACE_SYSCALL, sp->pid, 0, 0);
} else {
sig = signal & 0x7f;
if (sig != SIGSTOP) {
kappendf(&ob, PROLOGUE " %s%n", sp->pid, strsignal(sig));
Flush();
}
sig = sig;
kappendf(&ob, PROLOGUE " gottish signal %G%n", sp->pid, sig);
Flush();
ptrace(PTRACE_SYSCALL, sp->pid, 0, signal & 127);
}
// trace events always freeze the traced process
// this call will help it to start running again
ptrace(PTRACE_SYSCALL, sp->pid, 0, sig);
}
}

View file

@ -1,28 +0,0 @@
/*-*- 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 2020 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/nexgen32e/x86info.h"
#include "tool/decode/lib/x86idnames.h"
const struct IdName kX86GradeNames[] = {
{X86_GRADE_UNKNOWN, "Unknown"}, {X86_GRADE_APPLIANCE, "Appliance"},
{X86_GRADE_MOBILE, "Mobile"}, {X86_GRADE_TABLET, "Tablet"},
{X86_GRADE_DESKTOP, "Desktop"}, {X86_GRADE_CLIENT, "Client"},
{X86_GRADE_DENSITY, "Density"}, {X86_GRADE_SERVER, "Server"},
{X86_GRADE_SCIENCE, "Science"}, {0, 0},
};

View file

@ -1,46 +0,0 @@
/*-*- 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 2020 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/nexgen32e/x86info.h"
#include "tool/decode/lib/x86idnames.h"
const struct IdName kX86MarchNames[] = {
{X86_MARCH_UNKNOWN, "Unknown"},
{X86_MARCH_CORE2, "Core 2"},
{X86_MARCH_NEHALEM, "Nehalem"},
{X86_MARCH_WESTMERE, "Westmere"},
{X86_MARCH_SANDYBRIDGE, "Sandybridge"},
{X86_MARCH_IVYBRIDGE, "Ivybridge"},
{X86_MARCH_HASWELL, "Haswell"},
{X86_MARCH_BROADWELL, "Broadwell"},
{X86_MARCH_SKYLAKE, "Skylake"},
{X86_MARCH_KABYLAKE, "Kabylake"},
{X86_MARCH_CANNONLAKE, "Cannonlake"},
{X86_MARCH_ICELAKE, "Icelake"},
{X86_MARCH_TIGERLAKE, "Tigerlake"},
{X86_MARCH_BONNELL, "Bonnell"},
{X86_MARCH_SALTWELL, "Saltwell"},
{X86_MARCH_SILVERMONT, "Silvermont"},
{X86_MARCH_AIRMONT, "Airmont"},
{X86_MARCH_GOLDMONT, "Goldmont"},
{X86_MARCH_GOLDMONTPLUS, "Goldmont Plus"},
{X86_MARCH_TREMONT, "Tremont"},
{X86_MARCH_KNIGHTSLANDING, "Knights Landing"},
{X86_MARCH_KNIGHTSMILL, "Knights Mill"},
{0, 0},
};

View file

@ -22,7 +22,6 @@
(cosmo
'("__msabi"
"var"
"function"
"offsetof"
"microarchitecture"

View file

@ -1,6 +1,6 @@
SYNOPSIS
redbean.com [-hvduzmbagf] [-p PORT] [-- SCRIPTARGS...]
redbean.com [-hvduzmbagf] [-p PORT] [-D DIR] [-- SCRIPTARGS...]
DESCRIPTION
@ -1233,7 +1233,7 @@ UNIX MODULE
fork exit stat open close seek read write access fcntl chdir chown
chmod getcwd kill raise wait pipe dup mkdir rmdir opendir rename
link unlink symlink sync fsync fdatasync truncate umask getppid
getpgid setpgid getsid setsid getpid getuid getgid gettime
getpgrp getpgid setpgid getsid setsid getpid getuid getgid gettime
nanosleep socket socketpair bind listen accept connect recvfrom
sendto shutdown getpeername getsockname sigaction sigprocmask
strerror
@ -1260,19 +1260,77 @@ UNIX MODULE
There's also a /unix.lua file in redbean-demo.com that provides a
glimpse of how these powerful APIs can be used. Here's a synopsis:
unix.open(path, flags[, mode]) → fd, errno
Opens file.
unix.read(fd[, bufsiz, offset]) → data, errno
Reads from file descriptor.
unix.write(fd, data[, offset]) → rc, errno
Writes to file descriptor.
unix.close(fd) → rc, errno
Closes file descriptor.
unix.exit([exitcode]) → ⊥
Invokes `_Exit(exitcode)` on the process. This will immediately
halt the current process. Memory will be freed. File descriptors
will be closed. Any open connections it owns will be reset.
unix.fork() → childpid|0, errno
Creates a new process mitosis style. This returns twice. The
parent process gets the nonzero pid. The child gets zero.
unix.commandv(prog) → path, errno
Performs `$PATH` lookup of executable. We automatically suffix
`.com` and `.exe` automatically for all platforms when path
searching. By default, the current directory is not on the path.
If `prog` is an absolute path, then it's returned as-is. If
`prog` contains slashes then it's not path searched either and
will be returned if it exists.
unix.execve(prog, argv[, envp]) → errno
prog needs to be absolute, see commandv()
envp defaults to environ
Exits current process, replacing it with a new instance of the
specified program. `prog` needs to be an absolute path, see
commandv(). `envp` defaults to to the current `environ`. Both
`prog` and `envp` are arrays of strings.
unix.execve("/bin/ls", {"/bin/ls", "-hal"})
unix.exit(127)
The first element in `argv` should be `prog`. This function is
normally called after forking.
unix.access(path, mode) → rc, errno
mode can be: R_OK, W_OK, X_OK, F_OK
Checks if effective user of current process has permission to
access file. `mode` can be `R_OK`, `W_OK`, `X_OK`, or `F_OK` to
check for read, write, execute, and existence respectively.
unix.mkdir(path, mode) → rc, errno
mode should be octal
Makes directory. `mode` should be octal, e.g. `0755`.
unix.chdir(path) → rc, errno
Changes current directory to `path`.
unix.unlink(path) → rc, errno
Removes file at `path`.
unix.rmdir(path) → rc, errno
Removes empty directory at `path`.
unix.rename(oldpath, newpath) → rc, errno
unix.link(existingpath, newpath) → rc, errno
unix.symlink(target, linkpath) → rc, errno
@ -1290,67 +1348,131 @@ UNIX MODULE
unix.pipe([flags]) → reader, writer, errno
flags can have O_CLOEXEC
unix.getsid(pid) → sid, errno
unix.getpgrp() → pgid, errno
unix.getpgid(pid) → pgid, errno
unix.umask(mask) → rc, errno
unix.setpgid(pid, pgid) → pgid, errno
unix.setsid() → sid, errno
unix.getuid() → uid, errno
unix.getgid() → gid, errno
unix.umask(mask) → rc, errno
unix.gettime([clock]) → seconds, nanos, errno
unix.nanosleep(seconds, nanos) → remseconds, remnanos, errno
unix.sync(fd)
unix.fsync(fd) → rc, errno
unix.fdatasync(fd) → rc, errno
unix.open(path, flags[, mode]) → fd, errno
unix.close(fd) → rc, errno
unix.seek(fd, offset, whence) → newpos, errno
where whence ∈ {SEEK_SET, SEEK_CUR, SEEK_END}
whence defaults to SEEK_SET
unix.truncate(path, length) → rc, errno
unix.truncate(fd, length) → rc, errno
unix.read(fd[, bufsiz, offset]) → data, errno
unix.write(fd, data[, offset]) → rc, errno
unix.socket([family[, type[, protocol]]]) → fd, errno
SOCK_CLOEXEC may be or'd into type
family defaults to AF_INET
type defaults to SOCK_STREAM
protocol defaults to IPPROTO_TCP
`SOCK_CLOEXEC` may be or'd into type
`family` defaults to `AF_INET`
`type` defaults to `SOCK_STREAM`
`protocol` defaults to `IPPROTO_TCP`
unix.socketpair([family[, type[, protocol]]]) → fd1, fd2, errno
SOCK_CLOEXEC may be or'd into type
family defaults to AF_INET
type defaults to SOCK_STREAM
protocol defaults to IPPROTO_TCP
`SOCK_CLOEXEC` may be or'd into type
`family` defaults to `AF_INET`
`type` defaults to `SOCK_STREAM`
`protocol` defaults to `IPPROTO_TCP`
unix.bind(fd, ip, port) → rc, errno
SOCK_CLOEXEC may be or'd into type
family defaults to AF_INET
type defaults to SOCK_STREAM
protocol defaults to IPPROTO_TCP
unix.connect(fd, ip, port) → rc, errno
SOCK_CLOEXEC may be or'd into type
family defaults to AF_INET
type defaults to SOCK_STREAM
protocol defaults to IPPROTO_TCP
unix.listen(fd[, backlog]) → rc, errno
unix.getsockname(fd) → ip, port, errno
unix.getpeername(fd) → ip, port, errno
unix.accept(serverfd) → clientfd, ip, port, errno
unix.recv(fd[, bufsiz[, flags]]) → data, errno
`flags` can have MSG_{WAITALL,DONTROUTE,PEEK,OOB}, etc.
unix.recvfrom(fd[, bufsiz[, flags]]) → data, ip, port, errno
flags can have MSG_{WAITALL,DONTROUTE,PEEK,OOB}, etc.
`flags` can have MSG_{WAITALL,DONTROUTE,PEEK,OOB}, etc.
unix.send(fd, data[, flags]) → sent, errno
This is the same as `write` except it has a `flags` argument
that's intended for sockets. `flags` can have `MSG_OOB`,
`MSG_DONTROUTE`, or `MSG_NOSIGNAL`.
unix.sendto(fd, data, ip, port[, flags]) → sent, errno
flags MSG_OOB, MSG_DONTROUTE, MSG_NOSIGNAL, etc.
This is useful for sending messages over UDP sockets to specific
addresses. The `flags` parameter can have `MSG_OOB`,
`MSG_DONTROUTE`, or `MSG_NOSIGNAL`.
unix.shutdown(fd, how) → rc, errno
how can be SHUT_RD, SHUT_WR, or SHUT_RDWR
Partially closes socket. `how` can be `SHUT_RD`, `SHUT_WR`, or
`SHUT_RDWR`.
unix.sigprocmask(how[, mask]) → oldmask, errno
how can be SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
`how` can be `SIG_BLOCK`, `SIG_UNBLOCK`, `SIG_SETMASK`
unix.sigaction(sig[, handler[, flags[, mask]]]) → handler, flags, mask, errno
handler can be SIG_IGN, SIG_DFL, intptr_t, or a Lua function
sig can be SIGINT, SIGQUIT, SIGTERM, SIGUSR1, etc.
`handler` can be `SIG_IGN`, `SIG_DFL`, `intptr_t`, or a Lua
function. `sig` can be `SIGINT`, `SIGQUIT`, `SIGTERM`, etc.
`flags` can have `SA_RESTART`, `SA_RESETHAND`, etc. Example:
unix = require "unix"
unix.sigaction(unix.SIGUSR1, function(sig)
print(string.format("got %s", unix.strsignal(sig)))
end)
unix.sigprocmask(unix.SIG_SETMASK, -1)
unix.raise(unix.SIGUSR1)
unix.sigsuspend()
It's a good idea to not do too much work in a signal handler.
unix.sigsuspend([mask]) → errno
Waits for signal to be delivered.
unix.setitimer(which[, intsec, intmicros, valsec, valmicros])
→ intsec, intns, valsec, valns, errno
which should be ITIMER_REAL
unix.strerror(errno) → str
unix.strsignal(sig) → str
→ intsec, intns, valsec, valns, errno
Causes `SIGALRM` signals to be generated at some point(s) in the
future. The `which` parameter should be `ITIMER_REAL`.
Here's an example of how to create a 400 ms interval timer:
ticks = 0
unix.sigaction(unix.SIGALRM, function(sig)
print(string.format("tick no. %d", ticks))
ticks = ticks + 1
end)
unix.setitimer(unix.ITIMER_REAL, 0, 400000, 0, 400000)
while true do
unix.sigsuspend()
end
Here's how you'd do a single-shot timeout in 1 second:
unix.sigaction(unix.SIGALRM, MyOnSigAlrm, unix.SA_RESETHAND)
unix.setitimer(unix.ITIMER_REAL, 0, 0, 1, 0)
unix.strerror(errno:int) → str
Turns `errno` code into a string describing the error.
unix.strsignal(sig:int) → str
Turns platform-specific `sig` code into its name, e.g.
`strsignal(9)` always returns `"SIGKILL"`.
Here's your UnixStat* object.

View file

@ -425,6 +425,14 @@ static int LuaUnixGetsid(lua_State *L) {
return ReturnRc(L, rc, olderr);
}
// unix.getpgrp() → pgid, errno
static int LuaUnixGetpgrp(lua_State *L) {
int rc, olderr;
olderr = errno;
rc = getpgrp();
return ReturnRc(L, rc, olderr);
}
// unix.getpgid(pid) → pgid, errno
static int LuaUnixGetpgid(lua_State *L) {
int rc, pid, olderr;
@ -1427,6 +1435,7 @@ static const luaL_Reg kLuaUnix[] = {
{"truncate", LuaUnixTruncate}, // shrink or extend file medium
{"umask", LuaUnixUmask}, // set file mode creation mask
{"getppid", LuaUnixGetppid}, // get parent process id
{"getpgrp", LuaUnixGetpgrp}, // get process group id
{"getpgid", LuaUnixGetpgid}, // get process group id of pid
{"setpgid", LuaUnixSetpgid}, // set process group id for pid
{"getsid", LuaUnixGetsid}, // get session id of pid

View file

@ -98,6 +98,8 @@ o/$(MODE)/tool/net/redbean.com.dbg: \
$(APE)
@$(APELINK)
ifneq ($(MODE),tiny)
ifneq ($(MODE),tinylinux)
o/$(MODE)/tool/net/redbean.com: \
o/$(MODE)/tool/net/redbean.com.dbg \
o/$(MODE)/third_party/infozip/zip.com \
@ -118,6 +120,44 @@ o/$(MODE)/tool/net/redbean.com: \
tool/net/.init.lua \
tool/net/favicon.ico \
tool/net/redbean.png
endif
endif
o/tiny/tool/net/redbean.com: \
o/tiny/tool/net/redbean.com.dbg \
o/tiny/third_party/infozip/zip.com \
tool/net/net.mk \
tool/net/tiny/help.txt \
tool/net/.init.lua \
tool/net/favicon.ico \
tool/net/redbean.png
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
@$(COMPILE) -AMKDIR -T$@ mkdir -p o/tiny/tool/net/.redbean
@$(COMPILE) -ADD -T$@ dd if=$@ of=o/tiny/tool/net/.redbean/.ape bs=64 count=11 conv=notrunc 2>/dev/null
@$(COMPILE) -AZIP -T$@ o/tiny/third_party/infozip/zip.com -9qj $@ \
o/tiny/tool/net/.redbean/.ape \
tool/net/tiny/help.txt \
tool/net/.init.lua \
tool/net/favicon.ico \
tool/net/redbean.png
o/tinylinux/tool/net/redbean.com: \
o/tinylinux/tool/net/redbean.com.dbg \
o/tinylinux/third_party/infozip/zip.com \
tool/net/net.mk \
tool/net/tiny/help.txt \
tool/net/.init.lua \
tool/net/favicon.ico \
tool/net/redbean.png
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
@$(COMPILE) -AMKDIR -T$@ mkdir -p o/tinylinux/tool/net/.redbean
@$(COMPILE) -ADD -T$@ dd if=$@ of=o/tinylinux/tool/net/.redbean/.ape bs=64 count=11 conv=notrunc 2>/dev/null
@$(COMPILE) -AZIP -T$@ o/tinylinux/third_party/infozip/zip.com -9qj $@ \
o/tinylinux/tool/net/.redbean/.ape \
tool/net/tiny/help.txt \
tool/net/.init.lua \
tool/net/favicon.ico \
tool/net/redbean.png
# REDBEAN-DEMO.COM
#
@ -293,6 +333,8 @@ o/$(MODE)/tool/net/redbean-unsecure.o: tool/net/redbean.c o/$(MODE)/tool/net/red
# produce 200kb binary that's very similar to redbean as it existed on
# Hacker News the day it went viral.
ifneq ($(MODE),tiny)
ifneq ($(MODE),tinylinux)
o/$(MODE)/tool/net/redbean-original.com: \
o/$(MODE)/tool/net/redbean-original.com.dbg \
o/$(MODE)/third_party/infozip/zip.com \
@ -311,6 +353,38 @@ o/$(MODE)/tool/net/redbean-original.com: \
tool/net/help.txt \
tool/net/favicon.ico \
tool/net/redbean.png
endif
endif
o/tiny/tool/net/redbean-original.com: \
o/tiny/tool/net/redbean-original.com.dbg \
o/tiny/third_party/infozip/zip.com \
tool/net/tiny/help.txt \
tool/net/favicon.ico \
tool/net/redbean.png
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
@$(COMPILE) -AMKDIR -T$@ mkdir -p o/tiny/tool/net/.redbean-original
@$(COMPILE) -ADD -T$@ dd if=$@ of=o/tiny/tool/net/.redbean-original/.ape bs=64 count=11 conv=notrunc 2>/dev/null
@$(COMPILE) -AZIP -T$@ o/tiny/third_party/infozip/zip.com -9qj $@ \
o/tiny/tool/net/.redbean-original/.ape \
tool/net/tiny/help.txt \
tool/net/favicon.ico \
tool/net/redbean.png
o/tinylinux/tool/net/redbean-original.com: \
o/tinylinux/tool/net/redbean-original.com.dbg \
o/tinylinux/third_party/infozip/zip.com \
tool/net/tiny/help.txt \
tool/net/favicon.ico \
tool/net/redbean.png
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
@$(COMPILE) -AMKDIR -T$@ mkdir -p o/tinylinux/tool/net/.redbean-original
@$(COMPILE) -ADD -T$@ dd if=$@ of=o/tinylinux/tool/net/.redbean-original/.ape bs=64 count=11 conv=notrunc 2>/dev/null
@$(COMPILE) -AZIP -T$@ o/tinylinux/third_party/infozip/zip.com -9qj $@ \
o/tinylinux/tool/net/.redbean-original/.ape \
tool/net/tiny/help.txt \
tool/net/favicon.ico \
tool/net/redbean.png
o/$(MODE)/tool/net/redbean-original.com.dbg: \
$(TOOL_NET_DEPS) \

View file

@ -58,6 +58,7 @@
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/sock/goodsocket.internal.h"
#include "libc/sock/sock.h"
#include "libc/stdio/append.internal.h"
@ -504,13 +505,6 @@ static long ParseInt(const char *s) {
return strtol(s, 0, 0);
}
static void SyncSharedMemory(void) {
if (IsWindows() && !uniprocess) {
LOGIFNEG1(
msync(shared, ROUNDUP(sizeof(struct Shared), FRAMESIZE), MS_ASYNC));
}
}
static void *FreeLater(void *p) {
if (p) {
if (++freelist.n > freelist.c) {
@ -944,14 +938,11 @@ static void ProgramDirectory(const char *path) {
char *s;
size_t n;
struct stat st;
if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
DIEF("(cfg) error: not a directory: %`'s", path);
}
s = strdup(path);
n = strlen(s);
INFOF("(cfg) program directory: %s", s);
AddString(&stagedirs, s, n);
}
@ -1172,7 +1163,6 @@ static void ReportWorkerResources(int pid, struct rusage *ru) {
}
static void HandleWorkerExit(int pid, int ws, struct rusage *ru) {
SyncSharedMemory();
LockInc(&shared->c.connectionshandled);
AddRusage(&shared->children, ru);
ReportWorkerExit(pid, ws);
@ -1180,7 +1170,6 @@ static void HandleWorkerExit(int pid, int ws, struct rusage *ru) {
if (hasonprocessdestroy) {
LuaOnProcessDestroy(pid);
}
SyncSharedMemory();
}
static void KillGroupImpl(int sig) {
@ -6429,7 +6418,6 @@ static bool HandleMessage(void) {
ishandlingrequest = true;
r = HandleMessageActual();
ishandlingrequest = false;
SyncSharedMemory();
return r;
}
@ -6936,7 +6924,6 @@ static wontreturn void ExitWorker(void) {
MemDestroy();
CheckForMemoryLeaks();
}
SyncSharedMemory();
_Exit(0);
}

12
tool/net/tiny/help.txt Normal file
View file

@ -0,0 +1,12 @@
SYNOPSIS
redbean.com [-hvduzmbagf] [-p PORT] [-D DIR]
DESCRIPTION
redbean - single-file distributable web server
DOCUMENTATION
This binary was built in MODE=tiny or MODE=tinylinux
You can view documentation online at https://redbean.dev/