Conversation
1dc26d0 to
2f49fb2
Compare
ipc-channel relies on the fragments being read as atomic chunks, which is not guaranteed to be true for plain recvmsg(2) on SOCK_SEQPACKET cross-platform. Namely, on FreeBSD it's possible for this to return both more and less than a single fragment. SOCK_SEQPACKET can be thought of as a variant of SOCK_STREAM with the ability to set "end of record" markers using MSG_EOR. A single recvmsg(2) will not read past such a marker. While the fact that the marker has been reached is supposed to be communicated back to the caller through msg_flags, as of now Linux does not properly implement this on Unix-domain sockets. To handle cases where the recvmsg(2) returns less than a single fragment, include the size of the fragment in the header and continue reads until the entire fragment has been read. Since SOCK_SEQPACKET maintains ordering, as long as sending the fragments is atomic, this will not will not run the danger of interleaving of different messages. Empirically, sendmsg(2) as it is used by ipc-channel is atomic at least on FreeBSD. To make any possible resultant bugs easier to find, add asserts for that. Signed-off-by: Juhani Krekelä <juhani@krekelä.fi>
|
Investigating the failures here has lead me to discover that Linux using the dgram logic does mean that it mostly behaves as-if I have also edited the initial pull request message to reflect the current state of the code, as afaiu it will become the final commit message. |
ipc-channel relies on the fragments being read as atomic chunks, which is not guaranteed to be true for plain recvmsg(2) on SOCK_SEQPACKET cross-platform. Namely, on FreeBSD it's possible for this to return both more and less than a single fragment.
SOCK_SEQPACKET can be thought of as a variant of SOCK_STREAM with the ability to set "end of record" markers using MSG_EOR. A single recvmsg(2) will not read past such a marker. While the fact that the marker has been reached is supposed to be communicated back to the caller through msg_flags, as of now Linux does not properly implement this on Unix-domain sockets.
To handle cases where the recvmsg(2) returns less than a single fragment, include the size of the fragment in the header and continue reads until the entire fragment has been read. Since SOCK_SEQPACKET maintains ordering, as long as sending the fragments is atomic, this will not will not run the danger of interleaving of different messages.
Empirically, sendmsg(2) as it is used by ipc-channel is atomic at least on FreeBSD. To make any possible resultant bugs easier to find, add asserts for that.