aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-10-21 22:29:33 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-10-21 22:29:33 +0200
commite69e7c95bc68a90eadfbd963359737dce43d65f2 (patch)
treebd2e16484438f4f79ac33dfaf29ed193c76257b5
parenta29382ea5d52f3bf3668b13dfe9a5d39c4769031 (diff)
downloadsciteco-e69e7c95bc68a90eadfbd963359737dce43d65f2.tar.gz
fixed some interruptions of <EC> on Win32
* We now recreate the event loop with every call since it turned out that the idle watcher wouldn't be invoked after the event loop has been quit once. This at least fixes interruption of ECbash -c 'while true; do true; done'$. * Unfortunately, ECping -t 8.8.8.8$ still cannot be interrupted (unless you manually kill the process from the task manager).
-rw-r--r--TODO7
-rw-r--r--src/spawn.c29
2 files changed, 30 insertions, 6 deletions
diff --git a/TODO b/TODO
index e9bf2ac..f967b1d 100644
--- a/TODO
+++ b/TODO
@@ -16,11 +16,8 @@ Known Bugs:
https://github.com/Bill-Gray/PDCursesMod/issues/322
* Win32: Interrupting <EC> will sometimes hang.
Affects both PDCurses/WinGUI and Gtk.
- In this case you have to kill the subprocess using the task manager.
- Could this be a race condition when adding the process to the job object?
- Perhaps the child process should be created suspended before being added
- to the job object. Glib does not currently allow that.
- This could already be fixed.
+ This no longer happens with ECbash -c 'while true; do true; done'$.
+ However ECping -t 8.8.8.8$ still cannot be interrupted.
* dlmalloc's malloc_trim() does not seem to free any resident memory
after hitting the OOM limit, eg. after <%a>.
Apparently an effect of HAVE_MORECORE (sbrk()) - some allocation is
diff --git a/src/spawn.c b/src/spawn.c
index a1da5ff..99eb6e3 100644
--- a/src/spawn.c
+++ b/src/spawn.c
@@ -92,10 +92,12 @@ static void __attribute__((constructor))
teco_spawn_init(void)
{
memset(&teco_spawn_ctx, 0, sizeof(teco_spawn_ctx));
+ /* FIXME: Cannot share these objects between calls */
+#if 0
/*
* Context and loop can be reused between EC invocations.
* However we should not use the default context, since it
- * may be used by GTK
+ * may be used by GTK.
*/
teco_spawn_ctx.mainctx = g_main_context_new();
teco_spawn_ctx.mainloop = g_main_loop_new(teco_spawn_ctx.mainctx, FALSE);
@@ -108,6 +110,7 @@ teco_spawn_init(void)
g_source_set_callback(teco_spawn_ctx.idle_src, (GSourceFunc)teco_spawn_idle_cb,
NULL, NULL);
g_source_attach(teco_spawn_ctx.idle_src, teco_spawn_ctx.mainctx);
+#endif
}
static gchar **
@@ -286,6 +289,20 @@ teco_state_execute_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr
&stdin_fd, &stdout_fd, NULL, error))
goto gerror;
+ /*
+ * FIXME: At least on Win32, we cannot resume a main loop
+ * after it has been quit once, which is obviously a bug.
+ * Therefore, we cannot cache the context, loop and idle_src.
+ */
+ teco_spawn_ctx.mainctx = g_main_context_new();
+ teco_spawn_ctx.mainloop = g_main_loop_new(teco_spawn_ctx.mainctx, FALSE);
+
+ teco_spawn_ctx.idle_src = g_idle_source_new();
+ g_source_set_priority(teco_spawn_ctx.idle_src, G_PRIORITY_LOW);
+ g_source_set_callback(teco_spawn_ctx.idle_src, (GSourceFunc)teco_spawn_idle_cb,
+ NULL, NULL);
+ g_source_attach(teco_spawn_ctx.idle_src, teco_spawn_ctx.mainctx);
+
teco_spawn_ctx.child_src = g_child_watch_source_new(pid);
g_source_set_callback(teco_spawn_ctx.child_src, (GSourceFunc)teco_spawn_child_watch_cb,
NULL, NULL);
@@ -293,6 +310,9 @@ teco_state_execute_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr
teco_spawn_ctx.interrupted = FALSE;
#ifdef G_OS_WIN32
+ /*
+ * FIXME: In case of errors, we will leak memory.
+ */
teco_spawn_ctx.pid = CreateJobObject(NULL, NULL);
if (!teco_spawn_ctx.pid) {
teco_error_win32_set(error, "Cannot create job object", GetLastError());
@@ -406,6 +426,10 @@ teco_state_execute_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr
CloseHandle(teco_spawn_ctx.pid);
#endif
+ g_source_unref(teco_spawn_ctx.idle_src);
+ g_main_loop_unref(teco_spawn_ctx.mainloop);
+ g_main_context_unref(teco_spawn_ctx.mainctx);
+
/*
* NOTE: This includes interruptions following CTRL+C.
* But they are reported as G_SPAWN_ERROR_FAILED and hard to filter out.
@@ -828,10 +852,13 @@ teco_spawn_idle_cb(gpointer user_data)
static void TECO_DEBUG_CLEANUP
teco_spawn_cleanup(void)
{
+ /* FIXME: Cannot share these objects between calls */
+#if 0
g_source_unref(teco_spawn_ctx.idle_src);
g_main_loop_unref(teco_spawn_ctx.mainloop);
g_main_context_unref(teco_spawn_ctx.mainctx);
+#endif
if (teco_spawn_ctx.error)
g_error_free(teco_spawn_ctx.error);