sindresorhus / execa

Process execution for humans
MIT License
6.88k stars 219 forks source link

Timeout / cancel stuck process #1137

Closed zirkelc closed 3 months ago

zirkelc commented 3 months ago

Hey,

sorry for asking a question as an issue, I thought it might be a useful feature if it doesn't already exist. Execa has options for timeout and cancel signal.

I had a few cases where a process running a Node.js script got stuck because of an error, but the script didn't properly throw this error so the process kept running but didn't print anything to sdtout/stderr.

In such cases it would be nice to have timeout that resets after each update on on sdtout/stderr, so that you can distinguish a long running process from a stuck process.

ehmicky commented 3 months ago

Hi @zirkelc,

This is an interesting use case, but might be too specific to add as a built-in feature since it can be achieved by users with some additional code.

Instead, I would favor adding an example to the documentation, more specifically the Timeout section. The following example will terminate the subprocess if it did not print anything on stdout/stderr in the last minute.

import {execa} from 'execa';
import debounceFn from 'debounce-fn';

const NO_OUTPUT_TIMEOUT = 60000;
const controller = new AbortController();
const abort = debounceFn(controller.abort.bind(controller), {wait: NO_OUTPUT_TIMEOUT});

const subprocess = execa('npm', ['run', 'build'], {cancelSignal: controller.signal});
abort();
subprocess.stdout.on('data', abort);
subprocess.stderr.on('data', abort);
await subprocess;

@sindresorhus Do you think an example would be enough here? Also, what are your thoughts about this example?

zirkelc commented 3 months ago

Hi @ehmicky

thanks for this example, I was expecting it was already somehow possible 😄

sindresorhus commented 3 months ago

The example looks good and it's the right solution here.

zirkelc commented 3 months ago

Thank you for the help!