Skip to content

Commit

Permalink
Make improvements
Browse files Browse the repository at this point in the history
- Improved async signal safety of read() particularly for longjmp()
- Started adding cancel cleanup handlers for locks / etc on Windows
- Make /dev/tty work better particularly for uses like `foo | less`
- Eagerly read console input into a linked list, so poll can signal
- Fix some libc definitional bugs, which configure scripts detected
  • Loading branch information
jart committed Sep 21, 2023
1 parent d6c2830 commit 0c5dd7b
Show file tree
Hide file tree
Showing 85 changed files with 1,060 additions and 669 deletions.
52 changes: 52 additions & 0 deletions ape/ape-m1.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ struct Syslib {
int (*pthread_attr_destroy)(pthread_attr_t *);
int (*pthread_attr_setstacksize)(pthread_attr_t *, size_t);
int (*pthread_attr_setguardsize)(pthread_attr_t *, size_t);
/* v4 (2023-09-19) */
void (*exit)(int);
long (*close)(int);
long (*munmap)(void *, size_t);
long (*openat)(int, const char *, int, int);
long (*write)(int, const void *, size_t);
long (*read)(int, void *, size_t);
long (*sigaction)(int, const struct sigaction *, struct sigaction *);
long (*pselect)(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *);
long (*mprotect)(void *, size_t, int);
};

#define ELFCLASS32 1
Expand Down Expand Up @@ -792,14 +802,38 @@ static long sys_fork(void) {
return sysret(fork());
}

static long sys_close(int fd) {
return sysret(close(fd));
}

static long sys_pipe(int pfds[2]) {
return sysret(pipe(pfds));
}

static long sys_munmap(void *addr, size_t size) {
return sysret(munmap(addr, size));
}

static long sys_read(int fd, void *data, size_t size) {
return sysret(read(fd, data, size));
}

static long sys_mprotect(void *data, size_t size, int prot) {
return sysret(mprotect(data, size, prot));
}

static long sys_write(int fd, const void *data, size_t size) {
return sysret(write(fd, data, size));
}

static long sys_clock_gettime(int clock, struct timespec *ts) {
return sysret(clock_gettime((clockid_t)clock, ts));
}

static long sys_openat(int fd, const char *path, int flags, int mode) {
return sysret(openat(fd, path, flags, mode));
}

static long sys_nanosleep(const struct timespec *req, struct timespec *rem) {
return sysret(nanosleep(req, rem));
}
Expand All @@ -809,6 +843,15 @@ static long sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
return sysret((long)mmap(addr, size, prot, flags, fd, off));
}

static long sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
return sysret(sigaction(sig, act, oact));
}

static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds,
const struct timespec *timeout, const sigset_t *sigmask) {
return sysret(pselect(nfds, readfds, writefds, errorfds, timeout, sigmask));
}

int main(int argc, char **argv, char **envp) {
unsigned i;
int c, n, fd, rc;
Expand Down Expand Up @@ -852,6 +895,15 @@ int main(int argc, char **argv, char **envp) {
M->lib.pthread_attr_destroy = pthread_attr_destroy;
M->lib.pthread_attr_setstacksize = pthread_attr_setstacksize;
M->lib.pthread_attr_setguardsize = pthread_attr_setguardsize;
M->lib.exit = exit;
M->lib.close = sys_close;
M->lib.munmap = sys_munmap;
M->lib.openat = sys_openat;
M->lib.write = sys_write;
M->lib.read = sys_read;
M->lib.sigaction = sys_sigaction;
M->lib.pselect = sys_pselect;
M->lib.mprotect = sys_mprotect;

/* getenv("_") is close enough to at_execfn */
execfn = argc > 0 ? argv[0] : 0;
Expand Down
2 changes: 1 addition & 1 deletion build/definitions.mk
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ IGNORE := $(shell $(MKDIR) $(TMPDIR))

ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi silicon-wifi
HOSTS ?= pi silicon
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 rhel5 xnu win10 openbsd netbsd
Expand Down
2 changes: 1 addition & 1 deletion build/online.mk
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ o/$(MODE)/%.com.ok: \
o/$(MODE)/tool/build/runit.com \
o/$(MODE)/tool/build/runitd.com \
o/$(MODE)/%.com
$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)
@$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)

.PHONY:
o/tiny/tool/build/runit.com:
89 changes: 53 additions & 36 deletions examples/ttyinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "dsp/tty/tty.h"
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/select.h"
#include "libc/stdio/dprintf.h"
Expand All @@ -36,29 +39,30 @@
#define PROBE_DISPLAY_SIZE "\e7\e[9979;9979H\e[6n\e8"

char code[512];
int infd, outfd;
struct winsize wsize;
struct termios oldterm;
volatile bool resized, killed;

void onresize(void) {
void OnResize(int sig) {
resized = true;
}

void onkilled(int sig) {
void OnKilled(int sig) {
killed = true;
}

void restoretty(void) {
WRITE(1, DISABLE_MOUSE_TRACKING);
tcsetattr(1, TCSANOW, &oldterm);
void RestoreTty(void) {
WRITE(outfd, DISABLE_MOUSE_TRACKING);
tcsetattr(outfd, TCSANOW, &oldterm);
}

int rawmode(void) {
int EnableRawMode(void) {
static bool once;
struct termios t;
if (!once) {
if (!tcgetattr(1, &oldterm)) {
atexit(restoretty);
if (!tcgetattr(outfd, &oldterm)) {
atexit(RestoreTty);
} else {
perror("tcgetattr");
}
Expand All @@ -78,26 +82,26 @@ int rawmode(void) {

t.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON |
IGNBRK | BRKINT);
t.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL | ISIG);
t.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL /* | ISIG */);
t.c_cflag &= ~(CSIZE | PARENB);
t.c_oflag |= OPOST | ONLCR;
t.c_cflag |= CS8;
t.c_iflag |= IUTF8;

if (tcsetattr(1, TCSANOW, &t)) {
if (tcsetattr(outfd, TCSANOW, &t)) {
perror("tcsetattr");
}

/* WRITE(1, ENABLE_SAFE_PASTE); */
/* WRITE(1, ENABLE_MOUSE_TRACKING); */
/* WRITE(1, PROBE_DISPLAY_SIZE); */
WRITE(outfd, ENABLE_MOUSE_TRACKING);
/* WRITE(outfd, ENABLE_SAFE_PASTE); */
/* WRITE(outfd, PROBE_DISPLAY_SIZE); */
return 0;
}

void getsize(void) {
if (tcgetwinsize(1, &wsize) != -1) {
printf("termios says terminal size is %hu×%hu\r\n", wsize.ws_col,
wsize.ws_row);
void GetTtySize(void) {
if (tcgetwinsize(outfd, &wsize) != -1) {
dprintf(outfd, "termios says terminal size is %hu×%hu\r\n", wsize.ws_col,
wsize.ws_row);
} else {
perror("tcgetwinsize");
}
Expand Down Expand Up @@ -144,50 +148,63 @@ const char *describemouseevent(int e) {
// change the code above to enable ISIG if you want to trigger this
// then press ctrl-c or ctrl-\ in your pseudoteletypewriter console
void OnSignalThatWontEintrRead(int sig) {
dprintf(1, "got %s (read()ing will SA_RESTART)\n", strsignal(sig));
dprintf(outfd, "got %s (read()ing will SA_RESTART; try CTRL-D to exit)\n",
strsignal(sig));
}

void OnSignalThatWillEintrRead(int sig) {
dprintf(outfd, "got %s (read() operation will be aborted)\n", strsignal(sig));
}

int main(int argc, char *argv[]) {
int e, c, y, x, n, yn, xn;
infd = 0;
outfd = 1;
/* infd = outfd = open("/dev/tty", O_RDWR); */
signal(SIGTERM, OnKilled);
signal(SIGCONT, OnResize);
signal(SIGWINCH, OnResize);
signal(SIGINT, OnSignalThatWontEintrRead);
signal(SIGQUIT, OnSignalThatWontEintrRead);
xsigaction(SIGTERM, onkilled, 0, 0, NULL);
xsigaction(SIGWINCH, onresize, 0, 0, NULL);
xsigaction(SIGCONT, onresize, 0, 0, NULL);
rawmode();
getsize();
sigaction(SIGQUIT,
&(struct sigaction){.sa_handler = OnSignalThatWillEintrRead}, 0);
EnableRawMode();
GetTtySize();
while (!killed) {
if (resized) {
printf("SIGWINCH ");
getsize();
dprintf(outfd, "SIGWINCH ");
GetTtySize();
resized = false;
}
bzero(code, sizeof(code));
if ((n = readansi(0, code, sizeof(code))) == -1) {
if (errno == EINTR) continue;
if ((n = read(infd, code, sizeof(code))) == -1) {
if (errno == EINTR) {
dprintf(outfd, "read() was interrupted\n");
continue;
}
perror("read");
exit(1);
}
if (!n) {
printf("got stdin eof\n");
dprintf(outfd, "got stdin eof\n");
exit(0);
}
printf("%`'.*s (got %d) ", n, code, n);
dprintf(outfd, "%`'.*s (got %d) ", n, code, n);
if (iscntrl(code[0]) && !code[1]) {
printf("is CTRL-%c a.k.a. ^%c\r\n", CTRL(code[0]), CTRL(code[0]));
dprintf(outfd, "is CTRL-%c a.k.a. ^%c\r\n", CTRL(code[0]), CTRL(code[0]));
if (code[0] == CTRL('C') || code[0] == CTRL('D')) break;
} else if (startswith(code, "\e[") && endswith(code, "R")) {
yn = 1, xn = 1;
sscanf(code, "\e[%d;%dR", &yn, &xn);
printf("inband signalling says terminal size is %d×%d\r\n", xn, yn);
dprintf(outfd, "inband signalling says terminal size is %d×%d\r\n", xn,
yn);
} else if (startswith(code, "\e[<") &&
(endswith(code, "m") || endswith(code, "M"))) {
e = 0, y = 1, x = 1;
sscanf(code, "\e[<%d;%d;%d%c", &e, &y, &x, &c);
printf("mouse %s at %d×%d\r\n", describemouseevent(e | (c == 'm') << 2),
x, y);
dprintf(outfd, "mouse %s at %d×%d\r\n",
describemouseevent(e | (c == 'm') << 2), x, y);
} else {
printf("\r\n");
dprintf(outfd, "\r\n");
}
}
return 0;
Expand Down
14 changes: 0 additions & 14 deletions libc/calls/console.internal.h

This file was deleted.

2 changes: 2 additions & 0 deletions libc/calls/fstatfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ int fstatfs(int fd, struct statfs *sf) {
STRACE("fstatfs(%d, [%s]) → %d% m", fd, DescribeStatfs(rc, sf));
return rc;
}

__weak_reference(fstatfs, fstatfs64);
2 changes: 2 additions & 0 deletions libc/calls/getrlimit.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,5 @@ int getrlimit(int resource, struct rlimit *rlim) {
DescribeRlimit(rc, rlim), rc);
return rc;
}

__weak_reference(getrlimit, getrlimit64);
3 changes: 3 additions & 0 deletions libc/calls/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ int __ensurefds(int);
int __ensurefds_unlocked(int);
void __printfds(void);
uint32_t sys_getuid_nt(void);
int __pause_thread(uint32_t);
int CountConsoleInputBytes(int64_t);
int FlushConsoleInputBytes(int64_t);

forceinline int64_t __getfdhandleactual(int fd) {
return g_fds.p[fd].handle;
Expand Down
3 changes: 3 additions & 0 deletions libc/calls/interrupts-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/posixthread.internal.h"
Expand All @@ -33,7 +34,9 @@ textwindows int _check_interrupts(int sigops) {
goto Interrupted;
}
if (_weaken(__sig_check) && (status = _weaken(__sig_check)())) {
STRACE("syscall interrupted (status=%d, sigops=%d)", status, sigops);
if (status == 2 && (sigops & kSigOpRestartable)) {
STRACE("restarting system call");
return 0;
}
err = EINTR;
Expand Down
15 changes: 6 additions & 9 deletions libc/calls/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/console.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
Expand Down Expand Up @@ -91,10 +90,9 @@ static int ioctl_default(int fd, unsigned long request, void *arg) {
}

static int ioctl_fionread(int fd, uint32_t *arg) {
int rc;
uint32_t cm;
int64_t handle;
uint32_t avail;
int rc, e = errno;
if (!IsWindows()) {
return sys_ioctl(fd, FIONREAD, arg);
} else if (__isfdopen(fd)) {
Expand All @@ -106,19 +104,18 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
return _weaken(__winsockerr)();
}
} else if (GetFileType(handle) == kNtFileTypePipe) {
uint32_t avail;
if (PeekNamedPipe(handle, 0, 0, 0, &avail, 0)) {
*arg = avail;
return 0;
} else if (GetLastError() == kNtErrorBrokenPipe) {
return 0;
} else {
return __winerr();
}
} else if (GetConsoleMode(handle, &cm)) {
avail = CountConsoleInputBytes(handle);
if (avail == -1u && errno == ENODATA) {
errno = e;
avail = 0;
}
return avail;
int bytes = CountConsoleInputBytes(handle);
return MAX(0, bytes);
} else {
return eopnotsupp();
}
Expand Down
Loading

0 comments on commit 0c5dd7b

Please sign in to comment.