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

Proper way to write to FD 3 (on Windows)? #6305

Open
TooTallNate opened this issue Jun 15, 2020 · 8 comments
Open

Proper way to write to FD 3 (on Windows)? #6305

TooTallNate opened this issue Jun 15, 2020 · 8 comments
Labels
cli related to cli/ dir suggestion suggestions for new features (yet to be agreed)

Comments

@TooTallNate
Copy link

I'm trying to have deno output some information to file descriptor 3, so I am spawning deno like so:

$ deno run example.ts 3>three.txt

I have it working as expected by using /dev/fd/3:

const fd = Deno.openSync('/dev/fd/3', { read: false, write: true });
Deno.writeAllSync(fd, new TextEncoder().encode('hello'));
Deno.close(fd.rid);

Ok fine, good. But what I am really interested is learning the proper way to do this in a cross-platform way that will work on Windows.

Thanks in advance!

@ry
Copy link
Member

ry commented Jun 15, 2020

Deno doesn't expose file descriptors directly to the runtime - the resource ids often overlap but are not identical to FDs. I'm sorry to report that currently there's no way to do this.

Is this actually important? It's not inconceivable that we could make this work - but I'd like to understand the use-case better before dedicating time to it.

@TooTallNate
Copy link
Author

Really I'm just looking for a cross-platform solution (for Windows specifically) to /dev/fd/3.

@bartlomieju bartlomieju added cli related to cli/ dir suggestion suggestions for new features (yet to be agreed) labels Jun 16, 2020
@MarkTiedemann
Copy link
Contributor

MarkTiedemann commented Jun 16, 2020

Really I'm just looking for a cross-platform solution (for Windows specifically) to /dev/fd/3.

AFAIK, Windows doesn't have file descriptors. Also, there is no /dev/fd/3 device file (though other device files, such as, CON do exist).

May I ask why you want to write to /dev/fd/3?

PS: The Microsoft Visual C Runtime (MSVCRT) does provide an abstraction layer over Windows file handles so you can work with them similar to Unix file descriptors. I'm not aware of it abstracting /dev/**/**, though.

@MarkTiedemann
Copy link
Contributor

$ deno run example.ts 3>three.txt

In cmd.exe, handle no. 3 is a user-defined handle: https://web.archive.org/web/20171225062127id_/http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true

In powershell.exe, it is the "warning stream": https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection

@TooTallNate
Copy link
Author

TooTallNate commented Jun 17, 2020

May I ask why you want to write to /dev/fd/3?

I am passing structured data back up to the parent process, but can't use stdout in this case since this Deno script is importing other user code that will want to use stdout for their own purposes.

$ deno run example.ts 3>three.txt

That syntax I used was for Bash, as an example, but in reality I'm spawning Deno through a Node.js script doing something like this:

const child = spawn('deno', ['run', 'script.ts'], {
  stdio: ['ignore', 'inherit', 'inherit', 'pipe']
});

Notice the "pipe" for the FD 3, which causes child.stdio[3] to be a Readable stream to read out what the deno script writes to FD 3.

@MarkTiedemann
Copy link
Contributor

MarkTiedemann commented Jun 17, 2020

Notice the "pipe" for the FD 3, which causes child.stdio[3] to be a Readable stream

Is that stream readable from runtimes other than Node? And if so, how? I'm not sure how that works.


As an alternative, you could use alternate data streams. They work on NTFS, the main Windows file system.

// parent.js
const fs = require("fs");
const child_process = require("child_process");

fs.writeFileSync("child.ts", `Deno.writeTextFileSync("child.ts:stream", "hello parent");`);
child_process.spawnSync("deno", ["run", "--allow-write", "child.ts"]);
console.log(fs.readFileSync("child.ts:stream").toString("utf-8"));
> node parent.js
hello parent

@TooTallNate
Copy link
Author

Here is a comment about making the setup I'm trying to achieve work in Go: golang/go#21085 (comment) (the entire issue seems relevant actually)

@littledivy
Copy link
Member

Update: We added support for node:child_process IPC. It is implemented using named pipes on Windows and handles inherited by the process.

Ref #21490 & #21597

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cli related to cli/ dir suggestion suggestions for new features (yet to be agreed)
Projects
None yet
Development

No branches or pull requests

5 participants