Closed Stebalien closed 6 years ago
Note: I hit this when testing with a pipe (in a different package).
/cc @marten-seemann.
I initially wrote things this way to eplicitly avoid having an extra goroutine like this. But i guess 'goroutines are cheap', and we're opening streams way less often than we used to (though you want to change things mr @Stebalien )
Why could we deadlock when both peers are writing to the stream at the same time? Which stream muxers does this apply to?
@whyrusleeping we'll be using a different protocol (where the client will always speak first). Here:
@marten-seemann
Why could we deadlock when both peers are writing to the stream at the same time? Which stream muxers does this apply to?
The problem is that we aren't reading. We could also just assume that there's a small write buffer.
Note: the lazy negotiation streams (the fast path ones) already launch goroutines so I'm not so concerned here.
I think it’s a valid assumption that we have initially have enough flow control credit to write a protocol ID, so I’d prefer to keep things simple here.
I think it’s a valid assumption that we have initially have enough flow control credit to write a protocol ID...
This is more about buffering than control flow credit. For example, in a theoretical (but planned) "local" transport, each "stream" would just be a net.Pipe
. We could have a buffering requirement but I'd rather not, especially because net.Pipe
doesn't and go had rejected proposals to add a buffer multiple times.
I'm going with this for now. It's the conservative approach and we can loosen it up if we find performance issues.
Given that both sides now try to write the multistream handshake out before reading, we need to do it asynchronously. Otherwise, we can deadlock (depending on the protocol).
In practice, this shouldn't be an issue but I'm not sure if we can really guarantee that.
This fix does cost us an ephemeral goroutine but I'm not sure if we can get away from that.