From 34785420926593af933756dc11e91631ccd88698 Mon Sep 17 00:00:00 2001 From: j2rong4cn Date: Fri, 1 Aug 2025 23:49:22 +0800 Subject: [PATCH 1/5] chore: Windows Unix --- server.go | 12 ++++++------ server_test.go | 29 +++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/server.go b/server.go index b05af92d..bf32f81d 100644 --- a/server.go +++ b/server.go @@ -502,11 +502,6 @@ func Serve(opts *ServeConfig) { } select { case <-ctx.Done(): - // Cancellation. We can stop the server by closing the listener. - // This isn't graceful at all but this is currently only used by - // tests and its our only way to stop. - _ = listener.Close() - // If this is a grpc server, then we also ask the server itself to // end which will kill all connections. There isn't an easy way to do // this for net/rpc currently but net/rpc is more and more unused. @@ -514,6 +509,11 @@ func Serve(opts *ServeConfig) { s.Stop() } + // Cancellation. We can stop the server by closing the listener. + // This isn't graceful at all but this is currently only used by + // tests and its our only way to stop. + _ = listener.Close() + // Wait for the server itself to shut down <-doneCh @@ -526,7 +526,7 @@ func Serve(opts *ServeConfig) { } func serverListener(unixSocketCfg UnixSocketConfig) (net.Listener, error) { - if runtime.GOOS == "windows" { + if runtime.GOOS == "windows" && unixSocketCfg.socketDir == "" { return serverListener_tcp() } diff --git a/server_test.go b/server_test.go index 24bb3a35..f9d90bf9 100644 --- a/server_test.go +++ b/server_test.go @@ -9,8 +9,7 @@ import ( "log" "net" "os" - "path" - "runtime" + "path/filepath" "strings" "testing" "time" @@ -19,6 +18,9 @@ import ( ) func TestServer_testMode(t *testing.T) { + tmpDir := t.TempDir() + t.Setenv(EnvUnixSocketDir, tmpDir) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -68,6 +70,21 @@ func TestServer_testMode(t *testing.T) { if err := client.Ping(); err != nil { t.Fatalf("should not err: %s", err) } + // Grab the impl + raw, err := client.Dispense("test") + if err != nil { + t.Fatalf("err should be nil, got %s", err) + } + + tester, ok := raw.(testInterface) + if !ok { + t.Fatalf("bad: %#v", raw) + } + + n := tester.Double(3) + if n != 6 { + t.Fatal("invalid response", n) + } // Kill which should do nothing c.Kill() @@ -308,10 +325,6 @@ func TestServer_testStdLogger(t *testing.T) { } func TestUnixSocketDir(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("go-plugin doesn't support unix sockets on Windows") - } - tmpDir := t.TempDir() t.Setenv(EnvUnixSocketDir, tmpDir) @@ -344,8 +357,8 @@ func TestUnixSocketDir(t *testing.T) { t.Fatal("should've received reattach") } - actualDir := path.Clean(path.Dir(cfg.Addr.String())) - expectedDir := path.Clean(tmpDir) + actualDir := filepath.Clean(filepath.Dir(cfg.Addr.String())) + expectedDir := filepath.Clean(tmpDir) if actualDir != expectedDir { t.Fatalf("Expected socket in dir: %s, but was in %s", expectedDir, actualDir) } From 4d4018f5781a3a2e17bb113cf534de462c94d5f6 Mon Sep 17 00:00:00 2001 From: j2rong4cn Date: Sat, 2 Aug 2025 18:12:34 +0800 Subject: [PATCH 2/5] update server_test.go --- server_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server_test.go b/server_test.go index f9d90bf9..227f8537 100644 --- a/server_test.go +++ b/server_test.go @@ -104,6 +104,9 @@ func TestServer_testMode(t *testing.T) { } func TestServer_testMode_AutoMTLS(t *testing.T) { + tmpDir := t.TempDir() + t.Setenv(EnvUnixSocketDir, tmpDir) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() From 4fbc298572808afd24f0d888135d7752358cba3f Mon Sep 17 00:00:00 2001 From: j2rong4cn Date: Sat, 2 Aug 2025 20:32:50 +0800 Subject: [PATCH 3/5] optimize --- server.go | 52 ------------------------------------ server_test.go | 14 +++++----- server_unix.go | 9 +++++++ server_windows.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 58 deletions(-) create mode 100644 server_unix.go create mode 100644 server_windows.go diff --git a/server.go b/server.go index bf32f81d..a726c324 100644 --- a/server.go +++ b/server.go @@ -8,14 +8,12 @@ import ( "crypto/tls" "crypto/x509" "encoding/base64" - "errors" "fmt" "io" "net" "os" "os/signal" "os/user" - "runtime" "sort" "strconv" "strings" @@ -525,56 +523,6 @@ func Serve(opts *ServeConfig) { } } -func serverListener(unixSocketCfg UnixSocketConfig) (net.Listener, error) { - if runtime.GOOS == "windows" && unixSocketCfg.socketDir == "" { - return serverListener_tcp() - } - - return serverListener_unix(unixSocketCfg) -} - -func serverListener_tcp() (net.Listener, error) { - envMinPort := os.Getenv("PLUGIN_MIN_PORT") - envMaxPort := os.Getenv("PLUGIN_MAX_PORT") - - var minPort, maxPort int64 - var err error - - switch { - case len(envMinPort) == 0: - minPort = 0 - default: - minPort, err = strconv.ParseInt(envMinPort, 10, 32) - if err != nil { - return nil, fmt.Errorf("couldn't get value from PLUGIN_MIN_PORT: %v", err) - } - } - - switch { - case len(envMaxPort) == 0: - maxPort = 0 - default: - maxPort, err = strconv.ParseInt(envMaxPort, 10, 32) - if err != nil { - return nil, fmt.Errorf("couldn't get value from PLUGIN_MAX_PORT: %v", err) - } - } - - if minPort > maxPort { - return nil, fmt.Errorf("PLUGIN_MIN_PORT value of %d is greater than PLUGIN_MAX_PORT value of %d", minPort, maxPort) - } - - for port := minPort; port <= maxPort; port++ { - address := fmt.Sprintf("127.0.0.1:%d", port) - listener, err := net.Listen("tcp", address) - if err == nil { - return listener, nil - } - } - - return nil, errors.New("couldn't bind plugin TCP listener") -} - func serverListener_unix(unixSocketCfg UnixSocketConfig) (net.Listener, error) { tf, err := os.CreateTemp(unixSocketCfg.socketDir, "plugin") if err != nil { diff --git a/server_test.go b/server_test.go index 227f8537..a802a60d 100644 --- a/server_test.go +++ b/server_test.go @@ -10,17 +10,16 @@ import ( "net" "os" "path/filepath" + "runtime" "strings" "testing" "time" hclog "github.com/hashicorp/go-hclog" + "golang.org/x/sys/windows" ) func TestServer_testMode(t *testing.T) { - tmpDir := t.TempDir() - t.Setenv(EnvUnixSocketDir, tmpDir) - ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -104,9 +103,6 @@ func TestServer_testMode(t *testing.T) { } func TestServer_testMode_AutoMTLS(t *testing.T) { - tmpDir := t.TempDir() - t.Setenv(EnvUnixSocketDir, tmpDir) - ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -328,6 +324,12 @@ func TestServer_testStdLogger(t *testing.T) { } func TestUnixSocketDir(t *testing.T) { + if runtime.GOOS == "windows" { + major, _, build := windows.RtlGetNtVersionNumbers() + if major < 10 || build < 17063 { + t.Skip("go-plugin doesn't support unix sockets on Windows") + } + } tmpDir := t.TempDir() t.Setenv(EnvUnixSocketDir, tmpDir) diff --git a/server_unix.go b/server_unix.go new file mode 100644 index 00000000..29abe3bd --- /dev/null +++ b/server_unix.go @@ -0,0 +1,9 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +//go:build !windows +// +build !windows + +package plugin + +var serverListener = serverListener_unix diff --git a/server_windows.go b/server_windows.go new file mode 100644 index 00000000..317d4f59 --- /dev/null +++ b/server_windows.go @@ -0,0 +1,68 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +//go:build windows +// +build windows + +package plugin + +import ( + "errors" + "fmt" + "net" + "os" + "strconv" + + "golang.org/x/sys/windows" +) + +func serverListener(unixSocketCfg UnixSocketConfig) (net.Listener, error) { + major, _, build := windows.RtlGetNtVersionNumbers() + if major >= 10 && build >= 17063 { + unixSocketCfg.Group = "" + return serverListener_unix(unixSocketCfg) + } + return serverListener_tcp() +} + +func serverListener_tcp() (net.Listener, error) { + envMinPort := os.Getenv("PLUGIN_MIN_PORT") + envMaxPort := os.Getenv("PLUGIN_MAX_PORT") + + var minPort, maxPort int64 + var err error + + switch { + case len(envMinPort) == 0: + minPort = 0 + default: + minPort, err = strconv.ParseInt(envMinPort, 10, 32) + if err != nil { + return nil, fmt.Errorf("couldn't get value from PLUGIN_MIN_PORT: %v", err) + } + } + + switch { + case len(envMaxPort) == 0: + maxPort = 0 + default: + maxPort, err = strconv.ParseInt(envMaxPort, 10, 32) + if err != nil { + return nil, fmt.Errorf("couldn't get value from PLUGIN_MAX_PORT: %v", err) + } + } + + if minPort > maxPort { + return nil, fmt.Errorf("PLUGIN_MIN_PORT value of %d is greater than PLUGIN_MAX_PORT value of %d", minPort, maxPort) + } + + for port := minPort; port <= maxPort; port++ { + address := fmt.Sprintf("127.0.0.1:%d", port) + listener, err := net.Listen("tcp", address) + if err == nil { + return listener, nil + } + } + + return nil, errors.New("couldn't bind plugin TCP listener") +} From 27f3c9663106683b4633a0a8fc2042aa835b2634 Mon Sep 17 00:00:00 2001 From: j2rong4cn Date: Sun, 3 Aug 2025 12:44:18 +0800 Subject: [PATCH 4/5] optimize --- server_test.go | 4 +--- server_unix.go | 4 ++++ server_windows.go | 8 ++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/server_test.go b/server_test.go index a802a60d..5ce57c58 100644 --- a/server_test.go +++ b/server_test.go @@ -16,7 +16,6 @@ import ( "time" hclog "github.com/hashicorp/go-hclog" - "golang.org/x/sys/windows" ) func TestServer_testMode(t *testing.T) { @@ -325,8 +324,7 @@ func TestServer_testStdLogger(t *testing.T) { func TestUnixSocketDir(t *testing.T) { if runtime.GOOS == "windows" { - major, _, build := windows.RtlGetNtVersionNumbers() - if major < 10 || build < 17063 { + if isSupportUnix() { t.Skip("go-plugin doesn't support unix sockets on Windows") } } diff --git a/server_unix.go b/server_unix.go index 29abe3bd..6f779f67 100644 --- a/server_unix.go +++ b/server_unix.go @@ -7,3 +7,7 @@ package plugin var serverListener = serverListener_unix + +func isSupportUnix() bool { + return true +} diff --git a/server_windows.go b/server_windows.go index 317d4f59..2cd12cff 100644 --- a/server_windows.go +++ b/server_windows.go @@ -17,8 +17,7 @@ import ( ) func serverListener(unixSocketCfg UnixSocketConfig) (net.Listener, error) { - major, _, build := windows.RtlGetNtVersionNumbers() - if major >= 10 && build >= 17063 { + if isSupportUnix() { unixSocketCfg.Group = "" return serverListener_unix(unixSocketCfg) } @@ -66,3 +65,8 @@ func serverListener_tcp() (net.Listener, error) { return nil, errors.New("couldn't bind plugin TCP listener") } + +func isSupportUnix() bool { + major, _, build := windows.RtlGetNtVersionNumbers() + return major >= 10 && build >= 17063 +} From 0b2c3de69e83224ec4fcc4476371287626078283 Mon Sep 17 00:00:00 2001 From: j2rong4cn Date: Sun, 3 Aug 2025 12:50:42 +0800 Subject: [PATCH 5/5] . --- server_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_test.go b/server_test.go index 5ce57c58..22a569e2 100644 --- a/server_test.go +++ b/server_test.go @@ -324,7 +324,7 @@ func TestServer_testStdLogger(t *testing.T) { func TestUnixSocketDir(t *testing.T) { if runtime.GOOS == "windows" { - if isSupportUnix() { + if !isSupportUnix() { t.Skip("go-plugin doesn't support unix sockets on Windows") } }