mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 16:28:30 +00:00
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:
parent
933411ba99
commit
dc0ea6640e
127 changed files with 1354 additions and 866 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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},
|
||||
};
|
|
@ -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},
|
||||
};
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
(cosmo
|
||||
'("__msabi"
|
||||
"var"
|
||||
"function"
|
||||
"offsetof"
|
||||
"microarchitecture"
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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
12
tool/net/tiny/help.txt
Normal 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/
|
Loading…
Add table
Add a link
Reference in a new issue