diff --git a/internal/pipewire/securitycontext.go b/internal/pipewire/securitycontext.go index 107fe99..c50665b 100644 --- a/internal/pipewire/securitycontext.go +++ b/internal/pipewire/securitycontext.go @@ -4,6 +4,7 @@ import ( "errors" "io" "os" + "runtime" "syscall" ) @@ -125,8 +126,8 @@ type securityContextCloser struct { } // Close closes both ends of the pipe. -func (scc *securityContextCloser) Close() error { - return errors.Join( +func (scc *securityContextCloser) Close() (err error) { + err = errors.Join( syscall.Close(scc.closeFds[1]), syscall.Close(scc.closeFds[0]), // there is still technically a TOCTOU here but this is internal @@ -134,6 +135,10 @@ func (scc *securityContextCloser) Close() error { // receives trusted input (e.g. from cmd/hakurei) anyway os.Remove(scc.pathname), ) + + // no need for a finalizer anymore + runtime.SetFinalizer(scc, nil) + return } // BindAndCreate binds a new socket to the specified pathname and pass it to Create. @@ -162,6 +167,7 @@ func (securityContext *SecurityContext) BindAndCreate(pathname string, props SPA if err := syscall.Bind(listenFd, &syscall.SockaddrUnix{Name: pathname}); err != nil { return nil, os.NewSyscallError("bind", err) } else if err = syscall.Listen(listenFd, 0); err != nil { + _ = os.Remove(pathname) return nil, os.NewSyscallError("listen", err) } @@ -169,6 +175,8 @@ func (securityContext *SecurityContext) BindAndCreate(pathname string, props SPA _ = os.Remove(pathname) return nil, err } + runtime.SetFinalizer(&scc, (*securityContextCloser).Close) + if err := securityContext.Create(listenFd, scc.closeFds[1], props); err != nil { _ = scc.Close() return nil, err