You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After an RPC connection has been established, if the server closes the connection first,
the client.Close() call returns an error and doesn't close the socket file descriptor,
resulting in an FD leak.
To reproduce:
~ $ cat server.go
package main
import (
"log"
"net"
"net/rpc"
"os"
"time"
)
type MyRpc int
func (_ *MyRpc) Foo(arg1, arg2 *int) error {
return nil
}
func main() {
log.Println("server starting")
socketPath := "/tmp/test.sock"
os.Remove(socketPath)
go func() {
myRpc := new(MyRpc)
if err := rpc.Register(myRpc); err != nil {
log.Fatal(err)
}
addr := &net.UnixAddr{Net: "unix", Name: socketPath}
listener, err := net.ListenUnix("unix", addr)
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.AcceptUnix()
if err != nil {
log.Fatal(err)
}
rpc.ServeConn(conn)
}
}()
time.Sleep(2 * time.Second)
log.Println("server exiting")
}
~ $ cat client.go
package main
import (
"os/exec"
"fmt"
"log"
"net/rpc"
"os"
"time"
)
func showFds() {
procStr := fmt.Sprintf("/proc/%d/fd", os.Getpid())
cmd := exec.Command("ls", "-l", procStr)
output, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", output)
}
func main() {
log.Println("client starting")
client, err := rpc.Dial("unix", "/tmp/test.sock")
if err != nil {
log.Fatal(err)
}
log.Println("connection established")
log.Println("FDs before server exit:")
showFds()
time.Sleep(5 * time.Second)
log.Println("calling client.Close()")
if err := client.Close(); err != nil {
log.Println("client.Close() error: ", err)
}
log.Println("FDs after server exit:")
showFds()
log.Println("client exiting")
}
~ $ cat doit
go run server.go &
sleep 1
go run client.go
~ $ ./doit
2013/12/05 10:28:41 server starting
2013/12/05 10:28:42 client starting
2013/12/05 10:28:42 connection established
2013/12/05 10:28:42 FDs before server exit:
total 0
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 0 -> /dev/pts/5
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 1 -> /dev/pts/5
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 2 -> /dev/pts/5
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 3 -> socket:[4560708]
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 4 -> anon_inode:[eventpoll]
lr-x------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 6 -> pipe:[4560709]
2013/12/05 10:28:43 server exiting
2013/12/05 10:28:47 calling client.Close()
2013/12/05 10:28:47 client.Close() error: connection is shut down
2013/12/05 10:28:47 FDs after server exit:
total 0
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 0 -> /dev/pts/5
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 1 -> /dev/pts/5
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 2 -> /dev/pts/5
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 3 -> socket:[4560708]
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 4 -> anon_inode:[eventpoll]
lr-x------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 6 -> pipe:[4560712]
2013/12/05 10:28:47 client exiting
Notice the socket:[4560708] fd still exists after client.Close was called.
What steps will reproduce the problem?
See above programs and script.
What is the expected output?
The "socket:[4560708]" file descriptor should no longer be listed in the open
FDs for the client process.
What do you see instead?
lrwx------. 1 jpoimboe jpoimboe 64 Dec 5 10:28 3 -> socket:[4560708]
Which compiler are you using (5g, 6g, 8g, gccgo)?
6g
Which operating system are you using?
Linux
Which version are you using? (run 'go version')
go version go1.2 linux/amd64
Please provide any additional information below.
The text was updated successfully, but these errors were encountered:
by joshpoimboeuf:
The text was updated successfully, but these errors were encountered: