From 97d939a5f0ce17d5bbd936a7ec2f0c826ccb4457 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 17 Mar 2018 22:34:38 +0100 Subject: [PATCH] src: store fd for libuv streams on Windows On Windows, we can't just look up a FD for libuv streams and return it in `GetFD()`. However, we do sometimes construct streams from their FDs; in those cases, it should be okay to store the value on a class field. PR-URL: https://github.com/nodejs/node/pull/19377 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- src/pipe_wrap.cc | 1 + src/stream_wrap.cc | 6 ++++-- src/stream_wrap.h | 18 ++++++++++++++++++ src/tcp_wrap.cc | 1 + src/tty_wrap.cc | 1 + 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 7ec5bdf15be9cc..f3a88a2ecc80c3 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -204,6 +204,7 @@ void PipeWrap::Open(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); int err = uv_pipe_open(&wrap->handle_, fd); + wrap->set_fd(fd); if (err != 0) env->isolate()->ThrowException(UVException(err, "uv_pipe_open")); diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index ad708c9ed28def..0e700ba39a6b95 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -115,12 +115,14 @@ void LibuvStreamWrap::AddMethods(Environment* env, int LibuvStreamWrap::GetFD() { +#ifdef _WIN32 + return fd_; +#else int fd = -1; -#if !defined(_WIN32) if (stream() != nullptr) uv_fileno(reinterpret_cast(stream()), &fd); -#endif return fd; +#endif } diff --git a/src/stream_wrap.h b/src/stream_wrap.h index a97e8ba10f91d5..7847ebe754614a 100644 --- a/src/stream_wrap.h +++ b/src/stream_wrap.h @@ -88,6 +88,14 @@ class LibuvStreamWrap : public HandleWrap, public StreamBase { v8::Local target, int flags = StreamBase::kFlagNone); + protected: + inline void set_fd(int fd) { +#ifdef _WIN32 + fd_ = fd; +#endif + } + + private: static void GetWriteQueueSize( const v8::FunctionCallbackInfo& info); @@ -101,6 +109,16 @@ class LibuvStreamWrap : public HandleWrap, public StreamBase { static void AfterUvShutdown(uv_shutdown_t* req, int status); uv_stream_t* const stream_; + +#ifdef _WIN32 + // We don't always have an FD that we could look up on the stream_ + // object itself on Windows. However, for some cases, we open handles + // using FDs; In that case, we can store and provide the value. + // This became necessary because it allows to detect situations + // where multiple handles refer to the same stdio FDs (in particular, + // a possible IPC channel and a regular process.std??? stream). + int fd_ = -1; +#endif }; diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 70c60fa47cc68f..8200353b17bf99 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -212,6 +212,7 @@ void TCPWrap::Open(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(UV_EBADF)); int fd = static_cast(args[0]->IntegerValue()); uv_tcp_open(&wrap->handle_, fd); + wrap->set_fd(fd); } diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index d01caba4a558f2..cd8589cc7fc2e7 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -172,6 +172,7 @@ TTYWrap::TTYWrap(Environment* env, reinterpret_cast(&handle_), AsyncWrap::PROVIDER_TTYWRAP) { *init_err = uv_tty_init(env->event_loop(), &handle_, fd, readable); + set_fd(fd); if (*init_err != 0) MarkAsUninitialized(); }