Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It should be possible to handle SIGINT that is raised inside a looped prompt #27465

Open
finleyjb opened this issue Dec 24, 2024 · 1 comment

Comments

@finleyjb
Copy link

finleyjb commented Dec 24, 2024

Version: Deno 2.0.0

Given the following code:

// Example 1
Deno.addSignalListener("SIGINT", () => {
  console.log("interrupted!"); // Never prints
  Deno.exit();
});

while (true) {
  const val = prompt('Prompt: '); // Hit Ctrl-c while in this prompt
  console.log(val); // logs null
}

As it stands right now, this program will log a null and the SIGINT handler will never run. However, if I remove the loop and run this the SIGINT handler runs (adapted from the deno docs):

// Example 2
let sigint = false;
Deno.addSignalListener("SIGINT", () => {
  console.log("interrupted!");
  sigint = true;
});

const val = prompt("Prompt: ");
console.log(val); // prints null

// Add a timeout to prevent process exiting immediately.
setTimeout(() => {}, 5000); // prints "interrupted!"

The only workaround I've found is that you can yield control using a setTimeout in a promise:

// Example 3
Deno.addSignalListener("SIGINT", () => {
  console.log("interrupted!");
  Deno.exit(1);
});

while (true) {
  const val = prompt("Prompt: ");
  const printHandlerPromise = new Promise((resolve, reject) => {
    console.log(val);
    setTimeout(() => {
      resolve(null);
    }, 0);
  });
  await printHandlerPromise;
}

It seems like Example 1 should do something other than silently swallow the SIGINT function call. Perhaps the handler should run after the user inputs text at the next prompt?

@finleyjb finleyjb changed the title It should be possible to handle SIGINT that is raised inside looped prompt It should be possible to handle SIGINT that is raised inside a looped prompt Dec 24, 2024
@sigmaSd
Copy link
Contributor

sigmaSd commented Dec 24, 2024

You can use node readline

import * as readline from "node:readline/promises";
import process from "node:process";

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});
rl.addListener("SIGINT", () => {
  console.log("interrupted!"); // Never prints
  Deno.exit();
});

while (true) {
  const val = await rl.question("Prompt: "); // Hit Ctrl-c while in this prompt
  console.log(val); // logs null
}

prompt api is problematic in deno, its synchronous and it blocks all async tasks in deno, i imagine its not the case in browsers implementation

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

No branches or pull requests

2 participants