Improve redbean ctrl-c handling

This commit is contained in:
Justine Tunney 2022-04-21 15:24:44 -07:00
parent 1599b818d9
commit c39d6111f2
3 changed files with 89 additions and 21 deletions

View file

@ -580,8 +580,9 @@ static char abGrow(struct abuf *a, int need) {
int cap;
char *b;
cap = a->cap;
do cap += cap / 2;
while (cap < need);
do {
cap += cap / 2;
} while (cap < need);
if (!(b = realloc(a->b, cap * sizeof(*a->b)))) return 0;
a->cap = cap;
a->b = b;
@ -824,8 +825,9 @@ static char linenoiseGrow(struct linenoiseState *ls, size_t n) {
size_t m;
m = ls->buflen;
if (m >= n) return 1;
do m += m >> 1;
while (m < n);
do {
m += m >> 1;
} while (m < n);
if (!(p = realloc(ls->buf, m * sizeof(*ls->buf)))) return 0;
ls->buf = p;
ls->buflen = m;
@ -855,8 +857,9 @@ static size_t Forward(struct linenoiseState *l, size_t pos) {
static size_t Backward(struct linenoiseState *l, size_t pos) {
if (pos) {
do --pos;
while (pos && (l->buf[pos] & 0300) == 0200);
do {
--pos;
} while (pos && (l->buf[pos] & 0300) == 0200);
}
return pos;
}
@ -1461,8 +1464,9 @@ static size_t EscapeWord(struct linenoiseState *l) {
if (iswseparator(r.c)) break;
}
if ((j = i)) {
do --j;
while (j && (l->buf[j] & 0300) == 0200);
do {
--j;
} while (j && (l->buf[j] & 0300) == 0200);
r = GetUtf8(l->buf + j, l->len - j);
if (iswseparator(r.c)) break;
}
@ -1477,8 +1481,9 @@ static void linenoiseEditLeft(struct linenoiseState *l) {
static void linenoiseEditRight(struct linenoiseState *l) {
if (l->pos == l->len) return;
do l->pos++;
while (l->pos < l->len && (l->buf[l->pos] & 0300) == 0200);
do {
l->pos++;
} while (l->pos < l->len && (l->buf[l->pos] & 0300) == 0200);
linenoiseRefreshLine(l);
}
@ -2268,6 +2273,7 @@ char *linenoiseRaw(const char *prompt, int infd, int outfd) {
buf = 0;
raise(gotint);
errno = EINTR;
gotint = 0;
rc = -1;
}
if (rc != -1) {

View file

@ -17,9 +17,13 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/filter.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/user_regs_struct.h"
#include "libc/calls/ucontext.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
@ -28,6 +32,7 @@
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/pr.h"
#include "libc/sysv/consts/ptrace.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "tool/net/sandbox.h"
@ -75,6 +80,7 @@ static const struct sock_filter kSandboxFilter[] = {
_SECCOMP_ALLOW_SYSCALL(0x033), // getsockname
_SECCOMP_ALLOW_SYSCALL(0x034), // getpeername
_SECCOMP_ALLOW_SYSCALL(0x00f), // rt_sigreturn
_SECCOMP_ALLOW_SYSCALL(0x082), // rt_sigsuspend
_SECCOMP_ALLOW_SYSCALL(0x0e4), // clock_gettime
_SECCOMP_ALLOW_SYSCALL(0x060), // gettimeofday
_SECCOMP_ALLOW_SYSCALL(0x03f), // uname
@ -110,7 +116,12 @@ static const struct sock_fprog kSandbox = {
.filter = kSandboxFilter,
};
void OnSys(int sig, siginfo_t *si, ucontext_t *ctx) {
kprintf("Got SIGSYS%n");
}
int main(int argc, char *argv[]) {
sigset_t mask, origmask;
struct user_regs_struct regs;
int child, evpid, signal, wstatus;
@ -122,30 +133,68 @@ int main(int argc, char *argv[]) {
kprintf("Usage: %s PROGRAM [ARGS...]%n", argv[0]);
return 1;
}
ShowCrashReports();
CHECK_NE(-1, (child = fork()));
if (!child) {
if (ptrace(PTRACE_TRACEME) == -1) _Exit(124);
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) _Exit(125);
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &kSandbox) == -1) _Exit(126);
execvp(argv[1], argv + 1);
_Exit(127);
}
/* ShowCrashReports(); */
sigaction(SIGINT, &(struct sigaction){.sa_handler = SIG_IGN}, 0);
sigaction(SIGQUIT, &(struct sigaction){.sa_handler = SIG_IGN}, 0);
sigaction(SIGSYS,
&((struct sigaction){
.sa_sigaction = OnSys,
.sa_flags = SA_SIGINFO,
}),
0);
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, &origmask);
CHECK_NE(-1, (child = fork()));
if (!child) {
sigaction(SIGINT, &(struct sigaction){.sa_handler = SIG_DFL}, 0);
sigaction(SIGQUIT, &(struct sigaction){.sa_handler = SIG_DFL}, 0);
kprintf("CHILD ptrace(PTRACE_TRACEME)%n");
if (ptrace(PTRACE_TRACEME) == -1) {
kprintf("CHILD ptrace(PTRACE_TRACEME) failed %m%n");
_Exit(124);
}
kprintf("CHILD prctl(PR_SET_NO_NEW_PRIVS)%n");
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
kprintf("CHILD prctl(PR_SET_NO_NEW_PRIVS) failed %m%n");
_Exit(125);
}
kprintf("CHILD prctl(PR_SET_SECCOMP)%n");
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &kSandbox) == -1) {
kprintf("CHILD prctl(PR_SET_SECCOMP) failed %m%n");
_Exit(126);
}
kprintf("CHILD sigsuspend()%n");
if (sigsuspend(0) == -1) {
kprintf("CHILD sigsuspend() failed %m%n");
}
sigaction(SIGSYS, &(struct sigaction){.sa_handler = SIG_DFL}, 0);
sigprocmask(SIG_SETMASK, &origmask, 0);
execv(argv[1], argv + 1);
kprintf("CHILD execve(%#s) failed %m%n", argv[1]);
_Exit(127);
}
// wait for ptrace(PTRACE_TRACEME) to be called
kprintf("PARENT waitpid(child, &wstatus)%n");
CHECK_EQ(child, waitpid(child, &wstatus, 0));
// configure linux process tracing
kprintf("PARENT ptrace(PTRACE_SETOPTIONS)%n");
CHECK_NE(-1, ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESECCOMP));
// continue child process
kprintf("PARENT ptrace(PTRACE_CONT)%n");
CHECK_NE(-1, ptrace(PTRACE_CONT, child, 0, 0));
kprintf("PARENT kill(child, SIGSYS)%n");
kill(child, SIGSYS);
for (;;) {
kprintf("PARENT waitpid()%n");
CHECK_NE(-1, (evpid = waitpid(-1, &wstatus, __WALL)));
if (WIFSTOPPED(wstatus)) {
signal = (wstatus >> 8) & 0xffff;

View file

@ -6986,13 +6986,26 @@ static int EventLoop(int fd, int ms) {
static void ReplEventLoop(void) {
int status;
long double t;
lua_State *L = GL;
polls[0].fd = 0;
__nomultics = 2;
__replmode = true;
lua_initrepl("redbean");
linenoiseSetPollCallback(EventLoop);
while ((status = lua_loadline(L)) != -1) {
for (;;) {
if ((status = lua_loadline(L)) == -1) {
if (errno = EINTR) {
LockInc(&shared->c.pollinterrupts);
if (terminated) {
break;
} else {
continue;
}
} else {
break;
}
}
if (status == LUA_OK) {
status = lua_runchunk(L, 0, LUA_MULTRET);
}