From 06c268c274972692611a5ae27881adf5cb447ec3 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Tue, 11 Aug 2020 07:19:34 -0500 Subject: [PATCH] Start working on throwing errors from async functions. --- CHANGELOG.md | 5 ++++- src/core/fiber.h | 3 ++- src/core/net.c | 24 +++++++++++++++++++----- src/core/vm.c | 23 +++++++++++++++++++++++ src/include/janet.h | 1 + 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad3b16c9..4b4fb4f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ All notable changes to this project will be documented in this file. ## Unreleased - ??? +- Change `net/read`, `net/chunk`, and `net/write` to raise errors in the case of failures. +- Add `janet_continue_signal` to C API. This indirectly enables C functions that yield to the event loop + to raise errors or other signals. - Update meson build script to fix bug on Debian's version of meson - Add `xprint`, `xprin`, `xprintf`, and `xprinf`. -- `net/write` now returns an error message if write fails. +- `net/write` now raises an error message if write fails. - Fix issue with SIGPIPE on macOS and BSDs. ## 1.11.3 - 2020-08-03 diff --git a/src/core/fiber.h b/src/core/fiber.h index e99fa718..82427795 100644 --- a/src/core/fiber.h +++ b/src/core/fiber.h @@ -46,7 +46,8 @@ #define JANET_FIBER_MASK_USERN(N) (16 << (N)) #define JANET_FIBER_MASK_USER 0x3FF0 -#define JANET_FIBER_STATUS_MASK 0xFF0000 +#define JANET_FIBER_RESUME_SIGNAL 0x800000 +#define JANET_FIBER_STATUS_MASK 0x7F0000 #define JANET_FIBER_STATUS_OFFSET 16 #define JANET_FIBER_BREAKPOINT 0x1000000 diff --git a/src/core/net.c b/src/core/net.c index eccac2cd..06cd25eb 100644 --- a/src/core/net.c +++ b/src/core/net.c @@ -275,8 +275,11 @@ static size_t janet_loop_event(size_t index) { int ret = 1; int should_resume = 0; Janet resumeval = janet_wrap_nil(); + JanetSignal resumesignal = JANET_SIGNAL_OK; if (stream->flags & JANET_STREAM_CLOSED) { should_resume = 1; + resumeval = janet_cstringv("stream is closed"); + resumesignal = JANET_SIGNAL_ERROR; ret = 0; } else { switch (jlfd->event_type) { @@ -288,6 +291,8 @@ static size_t janet_loop_event(size_t index) { if (!(stream->flags & JANET_STREAM_READABLE)) { should_resume = 1; ret = 0; + resumesignal = JANET_SIGNAL_ERROR; + resumeval = janet_cstringv("stream not readable"); break; } JReadInt nread; @@ -309,6 +314,13 @@ static size_t janet_loop_event(size_t index) { should_resume = 1; if (nread > 0) { resumeval = janet_wrap_buffer(buffer); + } else { + if (nread == 0) { + resumeval = janet_cstringv("could not read from stream"); + } else { + resumeval = janet_cstringv(strerror(JLASTERR)); + } + resumesignal = JANET_SIGNAL_ERROR; } ret = 0; } else { @@ -342,6 +354,8 @@ static size_t janet_loop_event(size_t index) { const uint8_t *bytes; if (!(stream->flags & JANET_STREAM_WRITABLE)) { should_resume = 1; + resumesignal = JANET_SIGNAL_ERROR; + resumeval = janet_cstringv("stream not writeable"); ret = 0; break; } @@ -364,9 +378,9 @@ static size_t janet_loop_event(size_t index) { if (nwrote > 0) { start += nwrote; } else { + resumesignal = JANET_SIGNAL_ERROR; if (nwrote == -1) { - const uint8_t *msg = janet_formatc("write error: %s", strerror(JLASTERR)); - resumeval = janet_wrap_string(msg); + resumeval = janet_cstringv(strerror(JLASTERR)); } else { resumeval = janet_cstringv("could not write"); } @@ -396,7 +410,7 @@ static size_t janet_loop_event(size_t index) { if (NULL != jlfd->fiber && should_resume) { /* Resume the fiber */ Janet out; - JanetSignal sig = janet_continue(jlfd->fiber, resumeval, &out); + JanetSignal sig = janet_continue_signal(jlfd->fiber, resumeval, &out, resumesignal); if (sig != JANET_SIGNAL_OK && sig != JANET_SIGNAL_EVENT) { janet_stacktrace(jlfd->fiber, out); } @@ -654,7 +668,7 @@ static const JanetReg net_cfuns[] = { JDOC("(net/read stream nbytes &opt buf)\n\n" "Read up to n bytes from a stream, suspending the current fiber until the bytes are available. " "If less than n bytes are available (and more than 0), will push those bytes and return early. " - "Returns a buffer with up to n more bytes in it, or nil if the read failed.") + "Returns a buffer with up to n more bytes in it, or raises an error if the read failed.") }, { "net/chunk", cfun_stream_chunk, @@ -665,7 +679,7 @@ static const JanetReg net_cfuns[] = { "net/write", cfun_stream_write, JDOC("(net/write stream data)\n\n" "Write data to a stream, suspending the current fiber until the write " - "completes. Returns nil, or an error message if the write failed.") + "completes. Returns nil, or raises an error if the write failed.") }, { "net/close", cfun_stream_close, diff --git a/src/core/vm.c b/src/core/vm.c index a48f2434..3acea522 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -564,6 +564,15 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) { register Janet *stack; register uint32_t *pc; register JanetFunction *func; + + if (fiber->flags & JANET_FIBER_RESUME_SIGNAL) { + JanetSignal sig = (fiber->gc.flags & JANET_FIBER_STATUS_MASK) >> JANET_FIBER_STATUS_OFFSET; + fiber->gc.flags &= ~JANET_FIBER_STATUS_MASK; + fiber->flags &= ~(JANET_FIBER_RESUME_SIGNAL | JANET_FIBER_FLAG_MASK); + janet_vm_return_reg[0] = in; + return sig; + } + vm_restore(); if (fiber->flags & JANET_FIBER_DID_LONGJUMP) { @@ -1366,6 +1375,20 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) { return janet_continue_no_check(fiber, in, out); } +/* Enter the main vm loop but immediately raise a signal */ +JanetSignal janet_continue_signal(JanetFiber *fiber, Janet in, Janet *out, JanetSignal sig) { + JanetSignal tmp_signal = janet_check_can_resume(fiber, out); + if (tmp_signal) return tmp_signal; + if (sig != JANET_SIGNAL_OK) { + JanetFiber *child = fiber; + while (child->child) child = child->child; + child->gc.flags &= ~JANET_FIBER_STATUS_MASK; + child->gc.flags |= sig << JANET_FIBER_STATUS_OFFSET; + child->flags |= JANET_FIBER_RESUME_SIGNAL; + } + return janet_continue_no_check(fiber, in, out); +} + JanetSignal janet_pcall( JanetFunction *fun, int32_t argc, diff --git a/src/include/janet.h b/src/include/janet.h index ff6b26e0..946cfb16 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1412,6 +1412,7 @@ JANET_API int janet_symeq(Janet x, const char *cstring); JANET_API int janet_init(void); JANET_API void janet_deinit(void); JANET_API JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out); +JANET_API JanetSignal janet_continue_signal(JanetFiber *fiber, Janet in, Janet *out, JanetSignal sig); JANET_API JanetSignal janet_pcall(JanetFunction *fun, int32_t argn, const Janet *argv, Janet *out, JanetFiber **f); JANET_API JanetSignal janet_step(JanetFiber *fiber, Janet in, Janet *out); JANET_API Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv);