From 6d0b329b0d652ec9a24244161584e552502d2ddd Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Fri, 12 Jan 2024 11:34:15 -0700 Subject: [PATCH] cli-plugins: use non-abstract socket on darwin As macOS does not support the abstract socket namespace, use a temporary socket in $TMPDIR to connect with the plugin. Ensure this socket is cleaned up even in the case of crash/ungraceful termination by removing it after the first connection is accepted. Co-authored-by: Laura Brehm Signed-off-by: Bjorn Neergaard --- cli-plugins/socket/socket.go | 11 +++-------- cli-plugins/socket/socket_darwin.go | 19 +++++++++++++++++++ cli-plugins/socket/socket_nodarwin.go | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 cli-plugins/socket/socket_darwin.go create mode 100644 cli-plugins/socket/socket_nodarwin.go diff --git a/cli-plugins/socket/socket.go b/cli-plugins/socket/socket.go index 8f27c37439..a7ad00746b 100644 --- a/cli-plugins/socket/socket.go +++ b/cli-plugins/socket/socket.go @@ -16,7 +16,7 @@ const EnvKey = "DOCKER_CLI_PLUGIN_SOCKET" // SetupConn sets up a Unix socket listener, establishes a goroutine to handle connections // and update the conn pointer, and returns the environment variable to pass to the plugin. func SetupConn(conn **net.UnixConn) (string, error) { - listener, err := listen() + listener, err := listen("docker_cli_" + uuid.Generate().String()) if err != nil { return "", err } @@ -26,13 +26,6 @@ func SetupConn(conn **net.UnixConn) (string, error) { return EnvKey + "=" + listener.Addr().String(), nil } -func listen() (*net.UnixListener, error) { - return net.ListenUnix("unix", &net.UnixAddr{ - Name: "@docker_cli_" + uuid.Generate().String(), - Net: "unix", - }) -} - func accept(listener *net.UnixListener, conn **net.UnixConn) { defer listener.Close() @@ -41,6 +34,8 @@ func accept(listener *net.UnixListener, conn **net.UnixConn) { // ignore error here, if we failed to accept a connection, // conn is nil and we fallback to previous behavior *conn, _ = listener.AcceptUnix() + // perform any platform-specific actions on accept (e.g. unlink non-abstract sockets) + onAccept(*conn, listener) } }() } diff --git a/cli-plugins/socket/socket_darwin.go b/cli-plugins/socket/socket_darwin.go new file mode 100644 index 0000000000..17ab6aa69e --- /dev/null +++ b/cli-plugins/socket/socket_darwin.go @@ -0,0 +1,19 @@ +package socket + +import ( + "net" + "os" + "path/filepath" + "syscall" +) + +func listen(socketname string) (*net.UnixListener, error) { + return net.ListenUnix("unix", &net.UnixAddr{ + Name: filepath.Join(os.TempDir(), socketname), + Net: "unix", + }) +} + +func onAccept(conn *net.UnixConn, listener *net.UnixListener) { + syscall.Unlink(listener.Addr().String()) +} diff --git a/cli-plugins/socket/socket_nodarwin.go b/cli-plugins/socket/socket_nodarwin.go new file mode 100644 index 0000000000..893e465e4b --- /dev/null +++ b/cli-plugins/socket/socket_nodarwin.go @@ -0,0 +1,19 @@ +//go:build !darwin + +package socket + +import ( + "net" +) + +func listen(socketname string) (*net.UnixListener, error) { + return net.ListenUnix("unix", &net.UnixAddr{ + Name: "@" + socketname, + Net: "unix", + }) +} + +func onAccept(conn *net.UnixConn, listener *net.UnixListener) { + // do nothing + // while on darwin we would unlink here; on non-darwin the socket is abstract and not present on the filesystem +}