Skip to content

Commit

Permalink
Change how SIGALRM interrupts python.
Browse files Browse the repository at this point in the history
Rather than setting an resetting alarm(), set the alarm() once and
set/clear a flag to say if python is running.
Then interrupt python only if it is running.

Signed-off-by: NeilBrown <[email protected]>
  • Loading branch information
neilbrown committed Sep 15, 2023
1 parent 478d7c3 commit 44b01f1
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 31 deletions.
16 changes: 9 additions & 7 deletions DOC/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Core features
- [ ] If a pane wants to block mouse events from parents, as lib-view
does, it shouldn't need to catch all the combinations, or it
should be much easier
- [ ] gather memory usage stats per-pane and allow a dump
- [ ] gather memory usage stats per-pane, ensure 0 on close, and allow a dump
- [ ] show doc size in doc list - include undo size?
- [X] Ensure all panes that should use "Free" properly, and find some
way to encourage its use.
Expand Down Expand Up @@ -137,7 +137,7 @@ Core features
- [ ] design a way for a keystroke to interrupt a long-running function.
- [ ] extend Draw:measure protocol to allow constant-width-fonts to
cannot-scale displays can be detected and measurement optimised for.
- [ ] improve timeout. Set timer once, then set a flag so that all commands fail
- [X] improve timeout. Set timer once, then set a flag so that all commands fail
until some top-level clears the flag.
- [ ] reconsider all 'return comm_call()' calls. Do we every really
care if the callback succeeded?
Expand Down Expand Up @@ -171,6 +171,7 @@ Core features
the call which gave access to it, unless it registers for
notifications from the owner, and that probably only applies to
points.
- [ ] do something useful on SIGINT - maybe expedite times_up().

### Longer term

Expand All @@ -182,7 +183,7 @@ Core features
- [ ] support $SUBST in file-open path names ??
- [ ] Need a debug mode where every mark usage is checked for validity.
also check the setref sets up all linkages.
- [ ] remove all FIXMEs (there are 65) ... and any HACKs (2).
- [ ] remove all FIXMEs (there are 77) ... and any HACKs (5).
- [ ] Replace asserts with warnings where possible.
- [ ] hide view-num inside pane so number cannot be misused.
i.e. each view is owned by a pane and can only be used by that pane.
Expand Down Expand Up @@ -369,7 +370,8 @@ Module features

### pygtk

- [ ] can we capture the substates of character composition, and give feed-back?
- [ ] can we capture the substates of character composition, and give
feed-back?

### display-x11-xcb

Expand Down Expand Up @@ -413,7 +415,7 @@ Module features

### lib-macro

- [ ] don't allow starting macro inside a macro
- [X] don't allow starting macro inside a macro
- [ ] detect errors including Abort and search failure etc. Abort capture or
replay on error
- [ ] Possibly wait for a shell-command etc to complete before continuing.
Expand Down Expand Up @@ -443,7 +445,7 @@ Module features
- [ ] things slow down after lots of edits. Maybe track
number of chunk, marks, undos etc and display them somewhere
- [ ] stop consistency checking a doc when it gets "big" ??
- [ ] avoid infinite loops in consistency checks
- [X] avoid infinite loops in consistency checks
- [ ] doc-text: opening file with e.g. 200,000 lines is very slow
Check this..
- [ ] moving in a big file is slow - check this
Expand Down Expand Up @@ -780,7 +782,7 @@ Module features
### lang-python

- [ ] review python doc:char implementations for simplification.
- [ ] repeated alarm(10)/alarm(0) calls slow things down
- [X] repeated alarm(10)/alarm(0) calls slow things down
- [ ] array index should allow two args, second being a mark for
doc:get-attr etc.
- [ ] should be able to test if a mark is NULL or Freed
Expand Down
43 changes: 39 additions & 4 deletions core-editor.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <dlfcn.h>
Expand Down Expand Up @@ -202,7 +203,11 @@ DEF_CMD(editor_load_module)
return 1;
}
#endif
if (key_lookup_prefix(map, ci) > 0)
/* Multiple modules can support module lookup, such as
* global-load-modules:python or global-load-module:lua.
* So do a prefix lookup.
*/
if (key_lookup_prefix(map, ci, False) > 0)
return 1;
LOG("Failed to load module: %s", name);
return Efail;
Expand All @@ -216,15 +221,15 @@ DEF_CMD(editor_auto_event)
*/
struct ed_info *ei = ci->home->data;
struct map *map = ei->map;
int ret = key_lookup_prefix(map, ci);
int ret = key_lookup_prefix(map, ci, False);

if (ret)
return ret;
if (strcmp(ci->key, "event:refresh") == 0)
/* pointless to autoload for refresh */
return Efallthrough;
call("attach-libevent", ci->home);
return key_lookup_prefix(map, ci);
return key_lookup_prefix(map, ci, False);
}

DEF_CMD(editor_activate_display)
Expand Down Expand Up @@ -278,7 +283,7 @@ DEF_CMD(editor_multicall)
const char *key = ci->key;

((struct cmd_info*)ci)->key = ksuffix(ci, "global-multicall-");
ret = key_lookup_prefix(map, ci);
ret = key_lookup_prefix(map, ci, False);
((struct cmd_info*)ci)->key = key;
return ret;
}
Expand Down Expand Up @@ -686,6 +691,32 @@ DEF_CMD(global_find_file)
return Efalse;
}

static struct pane *editor;
static void catch(int sig)
{
struct cmd_info ci;
if (!editor)
return;
signal(sig, catch);
ci.home = editor;
ci.focus = editor;
ci.num = sig;
ci.num2 = 0;
ci.str = ci.str2 = NULL;
ci.mark = ci.mark2 = NULL;
ci.x = ci.y = 0;
switch (sig) {
case SIGALRM:
ci.key = "fast-alarm-";
key_lookup_prefix(editor->data->map, &ci, True);
break;
case SIGINT:
ci.key = "fast-interrupt-";
key_lookup_prefix(editor->data->map, &ci, True);
break;
}
}

struct pane *editor_new(const char *comm_name)
{
struct pane *ed;
Expand Down Expand Up @@ -728,5 +759,9 @@ struct pane *editor_new(const char *comm_name)
log_setup(ed);
window_setup(ed);

signal(SIGINT, catch);
signal(SIGALRM, catch);

editor = ed;
return ed;
}
11 changes: 9 additions & 2 deletions core-keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,12 @@ int key_lookup(struct map *m safe, const struct cmd_info *ci safe)
}
}

int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe)
int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe,
bool simple)
{
/* A "Simple" lookup avoids the backtrace. It is used in
* signal handlers.
*/
const char *k = ci->key;
int len = strlen(k);
int pos = key_find(m, k);
Expand All @@ -508,7 +512,10 @@ int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe)
if (comm && comm != prev) {
((struct cmd_info*)ci)->comm = comm;
((struct cmd_info*)ci)->key = m->keys[pos+i];
ret = do_comm_call(comm, ci);
if (simple)
ret = comm->func(ci);
else
ret = do_comm_call(comm, ci);
ASSERT(ret >= Efallthrough || ret < Eunused);
prev = comm;
/* something might have been added, recalc
Expand Down
4 changes: 4 additions & 0 deletions core-pane.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <unistd.h>

struct pane {
const char *name; /* For easy discovery in gdb */
struct pane *parent safe;
Expand Down Expand Up @@ -69,10 +71,12 @@ static inline struct pane * safe pane_root(struct pane *p safe)
static inline void time_starts(struct pane *p safe)
{
pane_set_time(pane_root(p));
alarm(15);
}

static inline void time_ends(struct pane *p safe)
{
alarm(0);
pane_end_time(pane_root(p));
}

Expand Down
3 changes: 2 additions & 1 deletion core.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,8 @@ struct map *safe key_alloc(void);
void key_free(struct map *m safe);
int key_handle(const struct cmd_info *ci safe);
int key_lookup(struct map *m safe, const struct cmd_info *ci safe);
int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe);
int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe,
bool simple);
struct command *key_lookup_cmd(struct map *m safe, const char *c safe);
void key_add(struct map *map safe, const char *k safe, struct command *comm);
void key_add_range(struct map *map safe,
Expand Down
37 changes: 20 additions & 17 deletions lang-python.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,12 +453,12 @@ static int dict_add(PyObject *kwds, char *name, PyObject *val)
return 1;
}

static void python_interrupt(int sig)
static bool python_running;
DEF_CB(handle_alarm)
{
/* Python code has been running for too long,
* interrupt it.
*/
kill(getpid(), 2);
if (python_running)
PyErr_SetInterrupt();
return 1;
}

REDEF_CB(python_call)
Expand Down Expand Up @@ -516,11 +516,9 @@ REDEF_CB(python_call)
Py_BuildValue("ii", ci->x, ci->y));

if (rv && pc->callable) {
signal(SIGALRM, python_interrupt);
alarm(10);
python_running = True;
ret = PyObject_Call(pc->callable, args, kwds);
alarm(0);
signal(SIGALRM, SIG_DFL);
python_running = False;
}

Py_DECREF(args);
Expand Down Expand Up @@ -1172,8 +1170,6 @@ static PyObject *Pane_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
int rv;
PyObject *s1, *s2;
struct pyret pr;
int remain;
sighandler_t oldhan;

if (!pane_valid(self))
return NULL;
Expand All @@ -1187,13 +1183,9 @@ static PyObject *Pane_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
return NULL;
}

remain = alarm(0);
oldhan = signal(SIGALRM, SIG_DFL);
python_running = False;
rv = key_handle(&ci);
if (oldhan != SIG_DFL) {
signal(SIGALRM, oldhan);
alarm(remain);
}
python_running = True;

/* Just in case ... */
PyErr_Clear();
Expand Down Expand Up @@ -2950,17 +2942,25 @@ void edlib_init(struct pane *ed safe)
PyObject *m;
PyConfig config;
char *argv[2]= { "edlib", NULL };
sighandler_t sigint;

if (edlib_module_path)
module_dir = strdup(edlib_module_path);
else
module_dir = ".";

/* de-register SIGINT while we initialise python,
* so that Python thinks that it's registration is
* valid - so PyErr_SetInterrupt() don't think there
* is a race.
*/
sigint = signal(SIGINT, SIG_DFL);
PyConfig_InitPythonConfig(&config);
config.isolated = 1;
PyConfig_SetBytesArgv(&config, 0, argv);
Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
signal(SIGINT, sigint);

PaneType.tp_new = PyType_GenericNew;
PaneIterType.tp_new = PyType_GenericNew;
Expand Down Expand Up @@ -3030,6 +3030,9 @@ void edlib_init(struct pane *ed safe)
EdlibModule = m;
ed_pane = ed;

call_comm("global-set-command", ed, &handle_alarm,
0, NULL, "fast-alarm-python");

call_comm("global-set-command", ed, &python_load_module,
0, NULL, "global-load-modules:python");
}

0 comments on commit 44b01f1

Please sign in to comment.