设置后是否无法关闭Deno.signal?

问题描述

let sig = Deno.signal(Deno.Signal.SIGINT)

await sig

console.log('hi')

执行上面的代码并将SIGINT传递给进程时,第一个SIGINT将恢复该进程。

但是,问题是 处理完信号后 SIGINT不再起作用。

所以,我试图使其工作。

let sig = Deno.signal(Deno.Signal.SIGINT)

await sig

sig.dispose()

console.log('hi')

这就是我所拥有的:

sig.dispose会在sig发生await时立即解析sig。(是否传递了SIGINT) 对于asyncIterator,它意味着返回done: true

与将SIGINT返回其原始状态无关。

这是打算吗?

解决方法

通常期望的处理信号流的方式如下:

const sig = Deno.signal(Deno.Signal.SIGINT);

// NOTICE: you might want to have a task running in the meantime to test this.
// Signals belong to the type of optional/unref-ed promises,in that awaiting
// on such promises does not block the runtime from exiting.
// You might want to add the line below for testing purposes.
setTimeout(() => {},100000);

// Async iterator. You can probably wrap it in a function such it does not
// block top level execution
for await (const _ of sig) {
  console.log("SIGINT captured");
}
SignalStream返回的

Deno.signal确实具有.then方法,因此您也可以采用以下样式:

const sig = Deno.signal(Deno.Signal.SIGINT);

setTimeout(() => {},100000);

while (true) {
  await sig;
  console.log("SIGINT captured");
}

应该等待多次。下面的示例在3个SIGINT触发器(在本地验证为可以正常工作)之后正确退出了该过程:

const sig = Deno.signal(Deno.Signal.SIGINT);

const timeout = setTimeout(() => {},100000);

await sig;
console.log("SIGINT captured #1");
await sig;
console.log("SIGINT captured #2");
await sig;
console.log("SIGINT captured #3,exiting");
clearTimeout(timeout);

console.log("DONE");
正如问题所提出的,

sig.dispose()确实确实起到了解除sig信号束缚的作用,并导致立即唤醒等待的应许。这是为了允许异步迭代器立即退出循环(如果有的话)。调用.dispose()之后,原来的sig将不再可用(由于关闭了后备信号资源并将其从内部资源表中删除)。您必须通过再次调用sig来创建新的Deno.signal(Deno.Signal.SIGINT)

const sig1 = Deno.signal(Deno.Signal.SIGINT);

const exitBlocker = setTimeout(() => {},100000);

await sig1;
console.log("SIGINT received by sig1. Disposing sig1");
sig1.dispose();

const sig2 = Deno.signal(Deno.Signal.SIGINT);

await sig1; // This should resolve immediately,even without signal
console.log("sig1 resolves immediately,but no actual signal happened");

await sig2;
console.log("SIGINT received by sig2. This is the real deal.");
await sig2;
console.log("SIGINT received by sig2 again. Preparing for exit.");

clearTimeout(exitBlocker);
console.log("DONE");

如果在本地运行以上命令,则会看到以下内容:

^CSIGINT received by sig1. Disposing sig1
sig1 resolves immediately,but no actual signal happened
^CSIGINT received by sig2. This is the real deal.
^CSIGINT received by sig2 again. Preparing for exit.
DONE