haskell / network

Low-level networking interface
http://hackage.haskell.org/package/network
Other
322 stars 186 forks source link

Add docs for shutting down sockets in a threaded scenario #548

Open voidus opened 1 year ago

voidus commented 1 year ago

Closes #545, see discussion there.

Basically, this is the documentation that I think would have helped me a few days ago.

I'm very much open to changing all it. The code example is a bit more complex than what I would like, but I thought it's better to show the situation where I needed it than to make it very simple.

kazu-yamamoto commented 1 year ago

shutdown is typically used to stop sending but continue receiving. If it is OK to stop the both sides, just use close.

voidus commented 1 year ago

I think the problem with close is that there are two places where you would want to do that.

Let's say you have a background thread that's listening on the socket. Given that the other side might also close it, there's probably a bracket _ close in there somewhere. But if we now close the socket from another thread, the file descriptor will be freed and possibly reused. If that happens before the bracket close runs, whatever uses the file descriptor now would be closed, right?

This makes a few assumptions about the way the operating system works, but it doesn't seem unrealistic to me. Using shutdown from the outside and waiting for the bracketed close to do it's thing seems safer.

kazu-yamamoto commented 1 year ago

I'm not sure I understand your programming model correctly but the top of the manual says:

The proper programming model is that one Socket is handled by a single thread. If multiple threads use one Socket concurrently, unexpected things would happen. There is one exception for multiple threads vs a single Socket: one thread reads data from a Socket only and the other thread writes data to the Socket only.

And when Socket is closed, the internal FD is set to (-1). No reuse problem will happen. See the document of unsafeFdSocket for more information.

voidus commented 1 year ago

I'm basically building a proxy with two sockets and one thread for each. One threads reads from socket A and writes to B, the other one does it the other way around. As far as I understand it, this pattern is explicitly covered by the part you quoted. Let's say the remote of socket A closes the connection. In this case, I want to shut down the connection to socket B, and I was unclear about how to do that. Hope that clears things up.

I missed that multiple calls to close are safe, thank you for pointing it out. I'll rewrite this to suggest closeing the socket rather than using shutdown.

I get that this might feel a bit unnecessary, but given the amount of pitfalls low-level network programming has, I think it would be very useful to users to be explicitly shown a way to do this that is safe.