From 85e27ed738229c2ae7571ce2b8d77e6fed5033a2 Mon Sep 17 00:00:00 2001 From: Geoff Goodman Date: Thu, 14 Sep 2023 16:29:34 -0400 Subject: [PATCH 1/2] src: port Pipe to uv_pipe_bind2, uv_pipe_connect2 The introduction of the uv_pipe_bind2 and uv_pipe_connect2 methods in libuv v1.46.0 changed the behaviour of uv_pipe_bind and uv_pipe_connect. This broke the ability to connect to abstract domain sockets on linux. This change ports PipeWrap to use the new uv_pipe_bind2 and uv_pipe_connect2 methods to restore abstract domain socket support. Fixes: https://github.com/nodejs/node/issues/49656 Refs: https://github.com/libuv/libuv/pull/4030 --- src/pipe_wrap.cc | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 944d7c3e72c534..738a51a140d0af 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -62,7 +62,6 @@ MaybeLocal PipeWrap::Instantiate(Environment* env, constructor->NewInstance(env->context(), 1, &type_value)); } - void PipeWrap::Initialize(Local target, Local unused, Local context, @@ -71,8 +70,7 @@ void PipeWrap::Initialize(Local target, Isolate* isolate = env->isolate(); Local t = NewFunctionTemplate(isolate, New); - t->InstanceTemplate() - ->SetInternalFieldCount(StreamBase::kInternalFieldCount); + t->InstanceTemplate()->SetInternalFieldCount(StreamBase::kInternalFieldCount); t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); @@ -102,9 +100,7 @@ void PipeWrap::Initialize(Local target, NODE_DEFINE_CONSTANT(constants, IPC); NODE_DEFINE_CONSTANT(constants, UV_READABLE); NODE_DEFINE_CONSTANT(constants, UV_WRITABLE); - target->Set(context, - env->constants_string(), - constants).Check(); + target->Set(context, env->constants_string(), constants).Check(); } void PipeWrap::RegisterExternalReferences(ExternalReferenceRegistry* registry) { @@ -152,7 +148,6 @@ void PipeWrap::New(const FunctionCallbackInfo& args) { new PipeWrap(env, args.This(), provider, ipc); } - PipeWrap::PipeWrap(Environment* env, Local object, ProviderType provider, @@ -163,16 +158,14 @@ PipeWrap::PipeWrap(Environment* env, // Suggestion: uv_pipe_init() returns void. } - void PipeWrap::Bind(const FunctionCallbackInfo& args) { PipeWrap* wrap; ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); node::Utf8Value name(args.GetIsolate(), args[0]); - int err = uv_pipe_bind(&wrap->handle_, *name); + int err = uv_pipe_bind2(&wrap->handle_, *name, name.length(), 0); args.GetReturnValue().Set(err); } - #ifdef _WIN32 void PipeWrap::SetPendingInstances(const FunctionCallbackInfo& args) { PipeWrap* wrap; @@ -183,7 +176,6 @@ void PipeWrap::SetPendingInstances(const FunctionCallbackInfo& args) { } #endif - void PipeWrap::Fchmod(const v8::FunctionCallbackInfo& args) { PipeWrap* wrap; ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); @@ -193,20 +185,17 @@ void PipeWrap::Fchmod(const v8::FunctionCallbackInfo& args) { args.GetReturnValue().Set(err); } - void PipeWrap::Listen(const FunctionCallbackInfo& args) { PipeWrap* wrap; ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); Environment* env = wrap->env(); int backlog; if (!args[0]->Int32Value(env->context()).To(&backlog)) return; - int err = uv_listen(reinterpret_cast(&wrap->handle_), - backlog, - OnConnection); + int err = uv_listen( + reinterpret_cast(&wrap->handle_), backlog, OnConnection); args.GetReturnValue().Set(err); } - void PipeWrap::Open(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -222,7 +211,6 @@ void PipeWrap::Open(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(err); } - void PipeWrap::Connect(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -237,10 +225,8 @@ void PipeWrap::Connect(const FunctionCallbackInfo& args) { ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_PIPECONNECTWRAP); - req_wrap->Dispatch(uv_pipe_connect, - &wrap->handle_, - *name, - AfterConnect); + req_wrap->Dispatch( + uv_pipe_connect2, &wrap->handle_, *name, name.length(), 0, AfterConnect); TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACING_CATEGORY_NODE2(net, native), "connect", @@ -251,7 +237,6 @@ void PipeWrap::Connect(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(0); // uv_pipe_connect() doesn't return errors. } - } // namespace node NODE_BINDING_CONTEXT_AWARE_INTERNAL(pipe_wrap, node::PipeWrap::Initialize) From 8afecf12f012833d8c10d3309243cc053d775043 Mon Sep 17 00:00:00 2001 From: Geoff Goodman Date: Fri, 15 Sep 2023 09:28:53 -0400 Subject: [PATCH 2/2] test: adds linux-only test for abstract sockets Introduce a new linux-only test for binding to an abstract unix socket and then making an http request against that socket. Refs: https://github.com/nodejs/node/issues/49656 --- .../test-pipe-abstract-socket-http.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/parallel/test-pipe-abstract-socket-http.js diff --git a/test/parallel/test-pipe-abstract-socket-http.js b/test/parallel/test-pipe-abstract-socket-http.js new file mode 100644 index 00000000000000..6d3beb44d1e277 --- /dev/null +++ b/test/parallel/test-pipe-abstract-socket-http.js @@ -0,0 +1,27 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +if (!common.isLinux) common.skip(); + +const server = http.createServer( + common.mustCall((req, res) => { + res.end('ok'); + }) +); + +server.listen( + '\0abstract', + common.mustCall(() => { + http.get( + { + socketPath: server.address(), + }, + common.mustCall((res) => { + assert.strictEqual(res.statusCode, 200); + server.close(); + }) + ); + }) +);