aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
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 /src
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).
Diffstat (limited to 'src')
-rw-r--r--src/spawn.c29
1 files changed, 28 insertions, 1 deletions
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);