Skip to content

feat(task-runner): stop running tasks when the process is interrupted - #837

Open
ddeboer wants to merge 3 commits into
mainfrom
fix/converter-stops-on-signal
Open

feat(task-runner): stop running tasks when the process is interrupted#837
ddeboer wants to merge 3 commits into
mainfrom
fix/converter-stops-on-signal

Conversation

@ddeboer

@ddeboer ddeboer commented Sep 8, 2026

Copy link
Copy Markdown
Member

NativeTaskRunner spawns each task with detached: true, in a process group of its own, so a Ctrl-C never reaches it; a container under the Docker daemon hears nothing of the process either. Nothing listened for SIGINT/SIGTERM, so interrupting the Node process – Ctrl-C during a long mapping, a cancelled CI job – left the JVMs running and the sparql-anything-* run directory behind.

The runner made its tasks immune to the signal, so the runner is where they get bound to the process again. That fixes it for every consumer at once – QLever’s index build and server had the same gap – rather than in the one converter that happened to be reported.

  • @lde/task-runner gains ChildTasks: a runner adds a task once it has started and deletes it once it has ended. While any runner in the process has a task going, one SIGINT/SIGTERM listener stops every task the way its runner’s stop() does, then ends the process as it would have without the listening: with the signal’s exit status (130/143) when nothing else listens for the signal, and otherwise however that listener ends it. The listener is removed the moment the signal arrives, so a second Ctrl-C ends the process at once when a task refuses to stop. Idle runners leave the process’s signal handling as they found it.
  • NativeTaskRunner and DockerTaskRunner bind each process/container to it. The native runner sends the group SIGTERM synchronously inside the listener, so even a host handler that calls process.exit(0) cannot orphan the processes.
  • SparqlAnythingConverter no longer listens for signals. It registers a synchronous 'exit' listener for the run’s duration that removes the run directory, which covers the runner ending the process as well as a host calling process.exit() mid-run.
  • Docs: a “Tasks end with the process” section on the task-runner page, linked from the native, Docker and SPARQL Anything pages.

Fix #831

@ddeboer ddeboer changed the title fix(sparql-anything): stop in-flight processes and clean up when the run is interrupted feat(task-runner): stop running tasks when the process is interrupted Sep 10, 2026
…run is interrupted

- Listen for SIGINT and SIGTERM for the duration of a run; on either, stop the processes
  still going, remove the run directory, drop the listeners and re-raise the signal so the
  process exits as it would have
- Each run registers its own listeners and removes only those, so parallel runs do not
  clobber each other
- Document the behaviour under “Converting several chunks at once”
- Add LiveTasks to @lde/task-runner: while any runner has a task going, the process
  listens for SIGINT and SIGTERM, stops every task the way the runner does, and then ends
  the process as it would have without the listening – with the signal’s exit status, or
  however another listener ends it. Listeners are removed as the signal arrives, so a
  second one ends the process at once.
- Bind every process NativeTaskRunner spawns and every container DockerTaskRunner starts
  to the process’s lifetime, so QLever’s index build and server are covered as well.
- Have SparqlAnythingConverter remove its run directory on process exit instead of
  listening for signals itself.
- Document the behaviour on the task-runner docs page and link to it from the runner and
  converter pages.
@ddeboer
ddeboer force-pushed the fix/converter-stops-on-signal branch from fb67550 to dbf0eed Compare September 10, 2026 11:51
- ChildTasks says whose tasks they are, and that they end with the parent; LiveTasks
  only said they were running.
- Keep it out of the task-runner docs page: it is for implementing a runner, and a
  runner’s users never see it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

task-runner-native: tasks outlive the process on SIGINT/SIGTERM

1 participant