mirror of https://github.com/golang/go.git
net: add (*UnixListener).SetUnlinkOnClose
Let users control whether unix listener socket file is unlinked on close. Fixes #13877. Change-Id: I9d1cb47e31418d655f164d15c67e188656a67d1c Reviewed-on: https://go-review.googlesource.com/32099 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
13558c41ff
commit
eb88b3eefa
|
|
@ -190,6 +190,18 @@ func (ln *UnixListener) file() (*os.File, error) {
|
|||
return f, nil
|
||||
}
|
||||
|
||||
// SetUnlinkOnClose sets whether the underlying socket file should be removed
|
||||
// from the file system when the listener is closed.
|
||||
//
|
||||
// The default behavior is to unlink the socket file only when package net created it.
|
||||
// That is, when the listener and the underlying socket file were created by a call to
|
||||
// Listen or ListenUnix, then by default closing the listener will remove the socket file.
|
||||
// but if the listener was created by a call to FileListener to use an already existing
|
||||
// socket file, then by default closing the listener will not remove the socket file.
|
||||
func (l *UnixListener) SetUnlinkOnClose(unlink bool) {
|
||||
l.unlink = unlink
|
||||
}
|
||||
|
||||
func listenUnix(ctx context.Context, network string, laddr *UnixAddr) (*UnixListener, error) {
|
||||
fd, err := unixSocket(ctx, network, laddr, nil, "listen")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -415,44 +415,104 @@ func TestUnixUnlink(t *testing.T) {
|
|||
t.Skip("unix test")
|
||||
}
|
||||
name := testUnixAddr()
|
||||
l, err := Listen("unix", name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
listen := func(t *testing.T) *UnixListener {
|
||||
l, err := Listen("unix", name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return l.(*UnixListener)
|
||||
}
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("cannot stat unix socket after ListenUnix: %v", err)
|
||||
checkExists := func(t *testing.T, desc string) {
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("unix socket does not exist %s: %v", desc, err)
|
||||
}
|
||||
}
|
||||
f, _ := l.(*UnixListener).File()
|
||||
l1, err := FileListener(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
checkNotExists := func(t *testing.T, desc string) {
|
||||
if _, err := os.Stat(name); err == nil {
|
||||
t.Fatalf("unix socket does exist %s: %v", desc, err)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("cannot stat unix socket after FileListener: %v", err)
|
||||
}
|
||||
if err := l1.Close(); err != nil {
|
||||
t.Fatalf("closing file listener: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("cannot stat unix socket after closing FileListener: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("cannot stat unix socket after closing FileListener and fd: %v", err)
|
||||
}
|
||||
l.Close()
|
||||
if _, err := os.Stat(name); err == nil {
|
||||
t.Fatal("closing unix listener did not remove unix socket")
|
||||
}
|
||||
if err := ioutil.WriteFile(name, []byte("hello world"), 0666); err != nil {
|
||||
t.Fatalf("cannot recreate socket file: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatal("recreating unix listener as file failed: %v", err)
|
||||
}
|
||||
l.Close()
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("second close of unix socket did second remove: %v", err)
|
||||
}
|
||||
os.Remove(name)
|
||||
|
||||
// Listener should remove on close.
|
||||
t.Run("Listen", func(t *testing.T) {
|
||||
l := listen(t)
|
||||
checkExists(t, "after Listen")
|
||||
l.Close()
|
||||
checkNotExists(t, "after Listener close")
|
||||
})
|
||||
|
||||
// FileListener should not.
|
||||
t.Run("FileListener", func(t *testing.T) {
|
||||
l := listen(t)
|
||||
f, _ := l.File()
|
||||
l1, _ := FileListener(f)
|
||||
checkExists(t, "after FileListener")
|
||||
f.Close()
|
||||
checkExists(t, "after File close")
|
||||
l1.Close()
|
||||
checkExists(t, "after FileListener close")
|
||||
l.Close()
|
||||
checkNotExists(t, "after Listener close")
|
||||
})
|
||||
|
||||
// Only first call to l.Close should remove.
|
||||
t.Run("SecondClose", func(t *testing.T) {
|
||||
l := listen(t)
|
||||
checkExists(t, "after Listen")
|
||||
l.Close()
|
||||
checkNotExists(t, "after Listener close")
|
||||
if err := ioutil.WriteFile(name, []byte("hello world"), 0666); err != nil {
|
||||
t.Fatalf("cannot recreate socket file: %v", err)
|
||||
}
|
||||
checkExists(t, "after writing temp file")
|
||||
l.Close()
|
||||
checkExists(t, "after second Listener close")
|
||||
os.Remove(name)
|
||||
})
|
||||
|
||||
// SetUnlinkOnClose should do what it says.
|
||||
|
||||
t.Run("Listen/SetUnlinkOnClose(true)", func(t *testing.T) {
|
||||
l := listen(t)
|
||||
checkExists(t, "after Listen")
|
||||
l.SetUnlinkOnClose(true)
|
||||
l.Close()
|
||||
checkNotExists(t, "after Listener close")
|
||||
})
|
||||
|
||||
t.Run("Listen/SetUnlinkOnClose(false)", func(t *testing.T) {
|
||||
l := listen(t)
|
||||
checkExists(t, "after Listen")
|
||||
l.SetUnlinkOnClose(false)
|
||||
l.Close()
|
||||
checkExists(t, "after Listener close")
|
||||
os.Remove(name)
|
||||
})
|
||||
|
||||
t.Run("FileListener/SetUnlinkOnClose(true)", func(t *testing.T) {
|
||||
l := listen(t)
|
||||
f, _ := l.File()
|
||||
l1, _ := FileListener(f)
|
||||
checkExists(t, "after FileListener")
|
||||
l1.(*UnixListener).SetUnlinkOnClose(true)
|
||||
f.Close()
|
||||
checkExists(t, "after File close")
|
||||
l1.Close()
|
||||
checkNotExists(t, "after FileListener close")
|
||||
l.Close()
|
||||
})
|
||||
|
||||
t.Run("FileListener/SetUnlinkOnClose(false)", func(t *testing.T) {
|
||||
l := listen(t)
|
||||
f, _ := l.File()
|
||||
l1, _ := FileListener(f)
|
||||
checkExists(t, "after FileListener")
|
||||
l1.(*UnixListener).SetUnlinkOnClose(false)
|
||||
f.Close()
|
||||
checkExists(t, "after File close")
|
||||
l1.Close()
|
||||
checkExists(t, "after FileListener close")
|
||||
l.Close()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue