experimental REPL interrupting
This commit is contained in:
parent
47e4e68eee
commit
7a21f9ef73
@ -237,6 +237,7 @@ void cbqn_runLine0(char* ln, i64 read) {
|
||||
|
||||
void cbqn_runLine(char* ln, i64 len) {
|
||||
if(CATCH) {
|
||||
cbqn_takeInterrupts(false);
|
||||
fprintf(stderr, "Error: "); printErrMsg(thrownMsg); fputc('\n', stderr);
|
||||
vm_pst(envCurr+1, envStart+envPrevHeight);
|
||||
freeThrown();
|
||||
@ -246,7 +247,9 @@ void cbqn_runLine(char* ln, i64 len) {
|
||||
gc_maybeGC();
|
||||
return;
|
||||
}
|
||||
cbqn_takeInterrupts(true);
|
||||
cbqn_runLine0(ln, len);
|
||||
cbqn_takeInterrupts(false);
|
||||
popCatch();
|
||||
}
|
||||
|
||||
|
||||
38
src/vm.c
38
src/vm.c
@ -843,7 +843,35 @@ B mnvmExecBodyInline(Body* body, Scope* sc) {
|
||||
|
||||
|
||||
|
||||
#if __has_include(<signal.h>) && REPL_INTERRUPT
|
||||
volatile int cbqn_interrupted;
|
||||
#include <signal.h>
|
||||
bool cbqn_takeInterrupts(bool b);
|
||||
static void interrupt_sigHandler(int x) {
|
||||
if (cbqn_interrupted) abort(); // shouldn't happen
|
||||
cbqn_takeInterrupts(false);
|
||||
cbqn_interrupted = 1;
|
||||
}
|
||||
bool cbqn_takeInterrupts(bool b) { // returns if succeeded
|
||||
if (!b) cbqn_interrupted = 0; // can be left dangling if nothing caught it
|
||||
struct sigaction act = {};
|
||||
act.sa_handler = b? interrupt_sigHandler : SIG_DFL;
|
||||
return sigaction(SIGINT, &act, NULL) == 0;
|
||||
}
|
||||
|
||||
NOINLINE NORETURN void cbqn_onInterrupt() {
|
||||
cbqn_interrupted = 0;
|
||||
thrM("interrupted");
|
||||
}
|
||||
#define CHECK_INTERRUPT ({ if (cbqn_interrupted) cbqn_onInterrupt(); })
|
||||
#else
|
||||
bool cbqn_takeInterrupts(bool b) { return false; }
|
||||
#define CHECK_INTERRUPT
|
||||
#endif
|
||||
|
||||
|
||||
FORCE_INLINE B execBlock(Block* block, Body* body, Scope* psc, i32 ga, B* svar) { // consumes svar contents
|
||||
CHECK_INTERRUPT;
|
||||
u16 varAm = body->varAm;
|
||||
assert(varAm>=ga);
|
||||
assert(ga == blockGivenVars(block));
|
||||
@ -1261,9 +1289,7 @@ void profiler_sigHandler(int x) {
|
||||
profiler_buf_c = bn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool setHandler(bool b) {
|
||||
static bool setProfHandler(bool b) {
|
||||
struct sigaction act = {};
|
||||
act.sa_handler = b? profiler_sigHandler : SIG_DFL;
|
||||
if (sigaction(SIGALRM/*SIGPROF*/, &act, NULL)) {
|
||||
@ -1272,7 +1298,7 @@ static bool setHandler(bool b) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool setTimer(i64 us) {
|
||||
static bool setProfTimer(i64 us) {
|
||||
struct itimerval timer;
|
||||
timer.it_value.tv_sec=0;
|
||||
timer.it_value.tv_usec=us;
|
||||
@ -1307,13 +1333,13 @@ bool profiler_active;
|
||||
bool profiler_start(i64 hz) {
|
||||
i64 us = 999999/hz;
|
||||
profiler_active = true;
|
||||
return setHandler(true) && setTimer(us);
|
||||
return setProfHandler(true) && setProfTimer(us);
|
||||
}
|
||||
bool profiler_stop() {
|
||||
if (!profiler_active) return false;
|
||||
profiler_active = false;
|
||||
if (profile_buf_full) fprintf(stderr, "Profiler buffer ran out in the middle of execution. Only timings of the start of profiling will be shown.\n");
|
||||
return setTimer(0) && setHandler(false);
|
||||
return setProfTimer(0) && setProfHandler(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
1
src/vm.h
1
src/vm.h
@ -236,6 +236,7 @@ NOINLINE B vm_fmtPoint(B src, B prepend, B path, usz cs, usz ce); // consumes pr
|
||||
NOINLINE void printErrMsg(B msg);
|
||||
NOINLINE void unwindEnv(Env* envNew); // envNew==envStart-1 for emptying the env stack
|
||||
NOINLINE void unwindCompiler(void); // unwind to the env of the invocation of the compiler; UB when not in compiler!
|
||||
bool cbqn_takeInterrupts(bool b);
|
||||
usz getPageSize(void);
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user