denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.19k stars 5.37k forks source link

Support opening raw file descriptors #6529

Open satyarohith opened 4 years ago

satyarohith commented 4 years ago

The ability to read and write to file descriptors other than stdin, stdout and stderr. See the example of nodejs below to get a better idea.

Node.js example:

const file = fs.createWriteStream(null, { fd: 3, encoding: "utf8" })
ry commented 4 years ago

Can you be a bit more descriptive? I'm not sure what you mean.

satyarohith commented 4 years ago

@ry updated! :)

jacobgc commented 4 years ago

@satyarohith is this what you're looking for? https://deno.land/std/fs

satyarohith commented 4 years ago

@jacobgc No, I'm trying to replicate the above example using Deno.

bartlomieju commented 4 years ago

CC @caspervonb

caspervonb commented 4 years ago

Related issue https://github.com/denoland/deno/issues/6305

Given that we have an intermediate representation of resources and do not expose file descriptors/handles directly it isn't immediately obvious (to me, at-least) how we should handle this.

First thing that comes to mind is a function to adopt foreign descriptors.

namespace Deno {
  export function foreign(fd : number) : Deno.File; // naming subject to a bikeshedding competition ;)
}

However, we can't do that as there is no way to enforce the sandboxing model when random file descriptors can be adopted so that's a dead end.

Supporting raw file descriptors as a general thing just can't be done without breaking the sandbox, such a call would at-least require full privileges.

But #6305 might be actionable as it's just about fd 3 which is a thing on windows and unix that we can map to a resource.

Spoonbender commented 4 years ago

It seems possible to get the file path given a file descriptor / handle, and enforce accordingly. It is also possible to allow access to raw file descriptors only if the global file system access was granted (though fds/handles may point at non-file kernel objects).

However, i agree that we should begin with support for the specific use cases we understand, and not rush to implement generic access to fds/handles.

cmorten commented 3 years ago

To add an example use-case, the Node net.Socket supports the passing of a pipe or tcp file descriptor (number) as the basis of the socket.

REF: https://github.com/nodejs/node/blob/master/lib/net.js#L327

Granted, this is marked as legacy in a code comment, but it is still documented in the official docs.

REF: https://nodejs.org/api/net.html#net_new_net_socket_options

This capability will be required if we wish to support full feature parity in our Node compatibility layer (https://github.com/denoland/deno_std/tree/main/node) for the net module.

Relates to:

CanadaHonk commented 1 year ago

There's also no way to use file descriptors (other than stdin/stdout/stderr) with spawned processes as far as I can tell.

ulken commented 1 year ago

I'm trying to use @clack/prompts with Deno but all prompts fail with:

Error: Not implemented: net.Socket.prototype.constructor with fd option
    at notImplemented (https://deno.land/std@0.177.0/node/_utils.ts:23:9)
    at new Socket (https://deno.land/std@0.177.0/node/net.ts:794:7)
    at new WriteStream (https://deno.land/std@0.177.0/node/tty.ts:21:8)

The particular usage of WriteStream is const sink = new WriteStream(0) (as seen here).

In tty.ts of Deno I find:

// TODO(kt3k): Implement tty.WriteStream class
export class WriteStream extends Socket {
}

I'm interested in knowing if this is on the roadmap/being worked on or if it never will be supported and I'd have to resort to using Node.js instead.

SaulMoonves commented 1 year ago

from #6305

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.

Hi, I just ran into this issue while trying something. On Linux, SystemD socket activation (kinda like inetd) launches the service on-demand with forwarded ports on file descriptors 3 and above, so it appears currently it is not possible to make a SystemD socket-activated Deno service. This is desirable because then I can delegate port-handling to systemd and lock down the service with private networking, and not run the program until the first time someone hits it. Of course from the security standpoint Deno can lock itself down pretty good so it's not super critical here but I was surprised. Cheers.

SaulMoonves commented 1 year ago

I have been informed one additional level of indirection can be used using systemd-socket-proxyd and achieve the same thing, so actually not critical.

mashirozx commented 1 year ago

I'm using a npm package, which throws an error:

error: Uncaught Error: Not implemented: net.Socket.prototype.constructor with fd option
    at notImplemented (ext:deno_node/_utils.ts:7:11)
    at new Socket (ext:deno_node/net.ts:453:13)
    at new WriteStream (ext:deno_node/tty.ts:18:8)
fernandolguevara commented 1 year ago

@bartlomieju I'm interested in implementing this missing code, can you give me some insight on where to start?

bitsnaps commented 1 year ago

I ran into similar issue trying to spin up a new Nuxt 3 app using:

deno run -A npm:nuxi init deno-nuxt

It should use the nuxi to create a new Nuxt 3 app, but I got:

 ERROR  Not implemented: net.Socket.prototype.constructor with fd option                                    3:23:32 PM

I'm running:

deno 1.36.3 (release, x86_64-apple-darwin)
v8 11.6.189.12
typescript 5.1.6

and Nuxi 3.6.5, everything works fine with Node and pnpm.

fernandolguevara commented 1 year ago

@bitsnaps a possible workaround could be to initialize the project with npm then run it with deno

benmccann commented 1 year ago

But https://github.com/denoland/deno/issues/6305 might be actionable as it's just about fd 3 which is a thing on windows and unix that we can map to a resource.

@caspervonb @bartlomieju I'm far outside my realm of expertise here, but is there also something we could do specifically for fd 0? It seems to be causing create-svelte and Nuxi to his this issue (e.g. SvelteKit uses the @clack/prompts library referred to in https://github.com/denoland/deno/issues/6529#issuecomment-1432690559). Or is there perhaps a workaround where we could ask those libraries not to use fd 0, but to access std in via a different method?

bartlomieju commented 1 year ago

@benmccann sorry for a late reply, I missed the notification. We're gonna focus on providing support for Socket with fds that are stdio streams. Expect PRs in the coming weeks.