deno: Deno.run with piped stdout gets stuck in specific scenarios

Reproduction

  1. Generate test file:
echo "hello world" > file.txt
for i in {1..10}; do cat file.txt file.txt > file2.txt && mv file2.txt file.txt; done
  1. create test.js
const proc = Deno.run({
  cmd: ["cat", "test.json"],
  stdout: "piped",
  stderr: "piped"
});

const status = await proc.status();
  1. run test.ts
deno --allow-run test.js
  1. Deno gets stuck on await proc.status().

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 5
  • Comments: 18 (13 by maintainers)

Commits related to this issue

Most upvoted comments

encountered same issue again! here is my work around:

const proc = Deno.run({ cmd, stderr: 'piped', stdout: 'piped' });
const [ stderr, stdout, status ] = await Promise.all([ proc.stderrOutput(), proc.output(), proc.status() ]);

I just ran into this again on the registry. It is a very annoying bug because it is so not logical. I think many people have and will run into it. I also ran into it for doc.deno.land. We should really address this one soon.

This happens when the stdout is bigger than (?) 64KiB, consider:

const p = Deno.run({

  // this will work in any case:
  // cmd: [ 'curl', '-s', 'https://deno.land' ], // 4KB

  // this will work only if stdout is drained below:
  cmd: [ 'curl', '-s', 'https://en.wikipedia.org/wiki/Deno_(software)' ], // 79KB

  stdout: 'piped',
  stderr: 'piped'
})

console.log('here 1')

// await p.output() // drain the stdout here
console.log('here 1.1')

await p.stderrOutput()
console.log('here 1.2')

const { code } = await p.status()
console.log('here 2, code: ' + code)

You have to uncomment the // drain the stdout here line to make the Wikipedia link work. Tested on Windows. Run with deno run --allow-run test.js.

So after further investigation I think this works as it should.

stdout and stderr pipes should be closed manually before awaiting on the status, so @rok-star’s solution is the preferable one for the time being. I will update the docs for the Deno.run API accordingly (edit: https://github.com/denoland/deno/pull/9390), but overall the API is not very user-friendly and I think it might have to undergo a rework for 2.0 to make it more like Tokio’s Child API (I will open a separate issue for it).

@lucacasonato I get the same issue when the sub process is asking for stdin (similar to what i mentioned before), it just hangs on the await p.status(), not sure in this scenario if it’s possible to address or even a bug

@ebebbington this should no longer be the case, calling p.status() will close stdin of the child process before awaiting on the status to avoid the deadlock (https://docs.rs/tokio/1.1.1/tokio/process/struct.Child.html#method.wait).

Still happening on latest canary

Everything works as expected when I add await proc.output() between the run call and the proc.status()call. await proc.stderrOutput() has no effect.