Make Ctrl-C clear line and re-prompt in REPL instead of exiting

Use sigsetjmp/siglongjmp to catch SIGINT during readline/fgets input
and jump back to the REPL loop with a fresh prompt. Running Lua code
still gets interrupted via the existing laction/lstop mechanism.

Fixes #11.
This commit is contained in:
Cormac Shannon
2026-02-28 23:34:22 +00:00
parent 47abb04921
commit af8300aa40
2 changed files with 28 additions and 2 deletions

View File

@@ -1,6 +1,6 @@
# Issue #11 — Ctrl-C REPL behaviour
**Status:** open
**Status:** resolved
## Problem

28
lua.c
View File

@@ -37,6 +37,11 @@ static lua_State *globalL = NULL;
static const char *progname = LUA_PROGNAME;
#include <setjmp.h>
static volatile sig_atomic_t sigint_in_repl = 0;
static sigjmp_buf repl_jmp;
#if defined(LUA_USE_POSIX) /* { */
@@ -81,6 +86,16 @@ static void laction (int i) {
}
static void repl_sigint_handler (int i) {
if (sigint_in_repl) {
sigint_in_repl = 0;
siglongjmp(repl_jmp, 1);
}
signal(i, SIG_DFL);
raise(i);
}
static void print_usage (const char *badoption) {
lua_writestringerror("%s: ", progname);
if (badoption[1] == 'e' || badoption[1] == 'l')
@@ -566,8 +581,11 @@ static int incomplete (lua_State *L, int status) {
static int pushline (lua_State *L, int firstline) {
char buffer[LUA_MAXINPUT];
size_t l;
char *b;
const char *prmt = get_prompt(L, firstline);
char *b = lua_readline(buffer, prmt);
sigint_in_repl = 1;
b = lua_readline(buffer, prmt);
sigint_in_repl = 0;
lua_pop(L, 1); /* remove prompt */
if (b == NULL)
return 0; /* no input */
@@ -678,11 +696,19 @@ static void doREPL (lua_State *L) {
const char *oldprogname = progname;
progname = NULL; /* no 'progname' on errors in interactive mode */
lua_initreadline(L);
setsignal(SIGINT, repl_sigint_handler);
if (sigsetjmp(repl_jmp, 1)) {
/* Ctrl-C during input — print newline, clear stack, re-prompt */
lua_writestringerror("%s", "\n");
lua_settop(L, 0);
setsignal(SIGINT, repl_sigint_handler);
}
while ((status = loadline(L)) != -1) {
if (status == LUA_OK)
status = docall(L, 0, LUA_MULTRET);
if (status == LUA_OK) l_print(L);
else report(L, status);
setsignal(SIGINT, repl_sigint_handler); /* re-install after docall */
}
lua_settop(L, 0); /* clear stack */
lua_writeline();