deno icon indicating copy to clipboard operation
deno copied to clipboard

Unable to kill a spawned process with a deno task

Open oscarotero opened this issue 1 year ago • 5 comments

Version: Deno 1.43.6

I have the following file to run a proxy.

  • It opens the server https://localhost:8000.
  • It also opens the secondary server https://localhost:3000 on demand to proxy all request to it.
  • The secondary server is closed after serving every request.
// ./proxy.ts

Deno.serve(async (request) => {
  // Start the server on demand
  const p = new Deno.Command(Deno.execPath(), {
    args: ["run", "-A", "server.ts"],
  });

  const process = p.spawn();

  // Wait for the server to start
  await waitForServer();

  // Change the port to the one you want to proxy to
  const url = new URL(request.url);
  url.port = "3000";

  const response = await fetch(url, request);
  
  // Kill the server
  process.kill();
  console.log("Server closed");
  return response;
});

async function waitForServer() {
  while (true) {
    try {
      await fetch("http://localhost:3000");
      break;
    } catch {
      console.log("Opening th server");
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
}

How the secondary server is created is irrelevant, but for completeness:

// ./server.ts

Deno.serve({
  handler: () => new Response("Hello, world!"),
  port: 3000,
});

This works great. The secondary server is opened and closed on demand.

But if the command is moved to a task:

// ./deno.json

{
  "tasks": {
    "run-server": "deno run -A server.ts"
  }
}

So the secondary server is started by running that task:

  const p = new Deno.Command(Deno.execPath(), {
    args: ["task", "run-server"],
  });

Now the server is created, but it's never closed. It there a way to effectively kill a process started with a task?

oscarotero avatar May 27 '24 15:05 oscarotero

You can do:

  const p = new Deno.Command(Deno.execPath(), {
    args: ["task", "run-server"],
  });
  p.spawn();
  // then when needed
  p.kill();

bartlomieju avatar May 27 '24 15:05 bartlomieju

This is what I do, but in the Deno.ChildProcess object returned by p.spawn().

  const p = new Deno.Command(Deno.execPath(), {
    args: ["task", "run-server"],
  });
  const child = p.spawn();
  // then when needed
  child.kill();

Deno.Command doesn't have the kill method: image

oscarotero avatar May 27 '24 15:05 oscarotero

The thing is it works if the command is ["run", "-A", "server.ts"] but doesn't work if I execute the same command throught a task (["task", "run-server"]).

oscarotero avatar May 27 '24 15:05 oscarotero

I believe this might be the same problem as in https://github.com/denoland/deno/issues/18445 after all.

bartlomieju avatar May 27 '24 18:05 bartlomieju

Okay, thanks! I will subscribe to that issue then!

oscarotero avatar May 27 '24 18:05 oscarotero

Closing as a dupe of #18445

lucacasonato avatar Jun 07 '24 17:06 lucacasonato