Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pipe handle leaks when reconnecting #18

Open
mharbison72 opened this issue Jul 14, 2023 · 0 comments
Open

Pipe handle leaks when reconnecting #18

mharbison72 opened this issue Jul 14, 2023 · 0 comments

Comments

@mharbison72
Copy link

I noticed this using ProcessExplorer from Sysinternals on Windows, with this trivial program and v1.2.2:

func main() {
	if len(os.Args) == 2 {
		s, err := ipc.StartServer("sdtool_pipe", nil)
		if err != nil {
			fmt.Println(err)
			return
		}

		for {
			if msg, err := s.Read(); err != nil {
				fmt.Println(err)
				continue
			} else {
				fmt.Printf("CLIENT MSG: %+v\n", msg)
			}

			err = s.Write(1, []byte("PONG"))

			if err == nil {
				// handle error
				fmt.Println(err)
			}
		}
	} else {
		c, err := ipc.StartClient("sdtool_pipe", nil)
		if err != nil {
			fmt.Println(err)
			return
		}

		for i := 0; i < 10; i++ {
			message, err := c.Read() // client

			if err != nil {
				fmt.Println(err)
				continue
			}

			fmt.Printf("GOT MSG: %+v\n", message)
			// do something with the received messages

			err = c.Write(1, []byte("PING"))

			if err != nil {
				fmt.Println(err)
				continue
			}
		}
	}
}

Then, running app.exe serve only starts the server side, and lists two separate \Device\NamedPipe\sdtool_pipe entries in the open HANDLEs list of ProcessExplorer. I'm not sure why two, but that's not a big deal. Running app.exe will spin up a client to connect, and that adds another reference to the pipe in the server (which persists after the client exits). Running the client again will add a 4th reference, etc.

I suspect the problem is the server accept loop unconditionally overwriting the old connection with the new one:

s.conn = conn
If I add a .Close() first, then the open file count rises to 3 for the first client run, but stays there for the second and further client runs (and I can see on old entry being cleaned up and a new one being added):

		if s.status == Listening || s.status == ReConnecting {

			if s.conn != nil {
				s.conn.Close()
			}

			s.conn = conn

I'm not sure if there's a way to get rid of the reference when the first client goes away, but wouldn't it be easier if the accept part was something the API user does, and that creates a separate object that manages each connection? That would seem to be the only way to handle multiple clients attempting to connect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant