From 3735b9c16b6569395e4e9e0a2feea827bb05c1e5 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Fri, 8 Jan 2021 16:40:43 +0900 Subject: [PATCH] Raise KeyboardInterrupt on ^C --- Makefile | 2 +- kuroko.c | 12 ++++++++++++ test/testKeyboardInterrupt.krk | 20 ++++++++++++++++++++ test/testKeyboardInterrupt.krk.expect | 1 + vm.c | 1 + vm.h | 1 + 6 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 test/testKeyboardInterrupt.krk create mode 100644 test/testKeyboardInterrupt.krk.expect diff --git a/Makefile b/Makefile index 1fe77bb..0b139ce 100644 --- a/Makefile +++ b/Makefile @@ -31,5 +31,5 @@ tags: $(wildcard *.c) $(wildcard *.h) .PHONY: test test: - @for i in test/*.krk; do echo $$i; ./kuroko $$i > $$i.expect; done + @for i in test/*.krk; do echo $$i; KUROKO_TEST_ENV=1 ./kuroko $$i > $$i.expect; done @git diff test/*.expect diff --git a/kuroko.c b/kuroko.c index c020ed5..9490f2a 100644 --- a/kuroko.c +++ b/kuroko.c @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef __toaru__ #include @@ -213,6 +214,14 @@ static void tab_complete_func(rline_context_t * c) { } #endif +static void handleSigint(int sigNum) { + if (vm.frameCount) { + krk_runtimeError(vm.exceptions.keyboardInterrupt, "Keyboard interrupt."); + } + + signal(sigNum, handleSigint); +} + /* Runs the interpreter to get the version information. */ static int version(void) { krk_initVM(0); @@ -296,6 +305,9 @@ int main(int argc, char * argv[]) { krk_initVM(flags); + /* Bind interrupt signal */ + signal(SIGINT, handleSigint); + #ifdef STATIC_ONLY /* Add any other modules you want to include that are normally built as shared objects. */ STATIC_MODULE(fileio); diff --git a/test/testKeyboardInterrupt.krk b/test/testKeyboardInterrupt.krk new file mode 100644 index 0000000..1176a80 --- /dev/null +++ b/test/testKeyboardInterrupt.krk @@ -0,0 +1,20 @@ +import time +import os + +if 'KUROKO_TEST_ENV' in os.environ: + print('(This test is skipped by the test suite.)') + return 0 + +print("This while loop should handle a ^C.") + +try: + while True: + print("Tick.") + time.sleep(1) +except: + print("Caught an exception:", exception.__class__.__name__) + +print("This loop will not...") +while True: + print("Tick.") + time.sleep(1) diff --git a/test/testKeyboardInterrupt.krk.expect b/test/testKeyboardInterrupt.krk.expect new file mode 100644 index 0000000..300a5f0 --- /dev/null +++ b/test/testKeyboardInterrupt.krk.expect @@ -0,0 +1 @@ +(This test is skipped by the test suite.) diff --git a/vm.c b/vm.c index 72a0ccd..929a13e 100644 --- a/vm.c +++ b/vm.c @@ -2622,6 +2622,7 @@ void krk_initVM(int flags) { ADD_EXCEPTION_CLASS(vm.exceptions.importError, "ImportError", vm.exceptions.baseException); ADD_EXCEPTION_CLASS(vm.exceptions.ioError, "IOError", vm.exceptions.baseException); ADD_EXCEPTION_CLASS(vm.exceptions.valueError, "ValueError", vm.exceptions.baseException); + ADD_EXCEPTION_CLASS(vm.exceptions.keyboardInterrupt, "KeyboardInterrupt", vm.exceptions.baseException); /* Build classes for basic types */ ADD_BASE_CLASS(vm.baseClasses.typeClass, "type", vm.objectClass); diff --git a/vm.h b/vm.h index a239ee4..eb97343 100644 --- a/vm.h +++ b/vm.h @@ -78,6 +78,7 @@ typedef struct { KrkClass * importError; KrkClass * ioError; KrkClass * valueError; + KrkClass * keyboardInterrupt; } exceptions; struct {