Discussion:
Attempting to receivce zero-length message with recvmsg
Tamas Szakaly
2018-09-10 08:58:33 UTC
Permalink
Hi,

I have a question about the recvmsg syscall. According to POSIX, unless
O_NONBLOCK is set on the socket fd, recvmsg [1] should block until a message
arrives. However, recvmsg returns immediately with 0, if we are trying to
receive a 0-byte message from a SOCK_SEQPACKET AF_UNIX socket. Consider the
following code:

#include <stdio.h>
#include <sys/socket.h>

int main(int argc, char** argv) {
int sock[2];
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sock);

struct msghdr msghdr = {0};
int ret = recvmsg(sock[1], &msghdr, 0);

printf("ret=%d, msghdr.msg_flags=0x%08x\n\n", ret, msghdr.msg_flags);
}

Running this yields this output:

[0x00 socketstuff]$ cc socketpair.c -o socketpair && ./socketpair
ret=0, msghdr.msg_flags=0x00000000

You can see that recvmsg returns with 0, even though there were no messages
sent, and neither of the sockets are closed, so it should block indefinitely.

Is this behavior intentional to match the semantics of read [2] (i.e.
attempting to read zero bytes should be a no-op)?


[1] recvmsg: http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
[2] read: http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
--
Tamas Szakaly
@sghctoma
Gary Jennejohn
2018-09-10 15:28:32 UTC
Permalink
On Mon, 10 Sep 2018 10:58:33 +0200
Post by Tamas Szakaly
Hi,
I have a question about the recvmsg syscall. According to POSIX, unless
O_NONBLOCK is set on the socket fd, recvmsg [1] should block until a message
arrives. However, recvmsg returns immediately with 0, if we are trying to
receive a 0-byte message from a SOCK_SEQPACKET AF_UNIX socket. Consider the
#include <stdio.h>
#include <sys/socket.h>
int main(int argc, char** argv) {
int sock[2];
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sock);
struct msghdr msghdr = {0};
int ret = recvmsg(sock[1], &msghdr, 0);
printf("ret=%d, msghdr.msg_flags=0x%08x\n\n", ret, msghdr.msg_flags);
}
[0x00 socketstuff]$ cc socketpair.c -o socketpair && ./socketpair
ret=0, msghdr.msg_flags=0x00000000
You can see that recvmsg returns with 0, even though there were no messages
sent, and neither of the sockets are closed, so it should block indefinitely.
Is this behavior intentional to match the semantics of read [2] (i.e.
attempting to read zero bytes should be a no-op)?
[1] recvmsg: http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
[2] read: http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
You have to initalize msghdr.msg_iov and msghde.iov_len, otherwise
the kernel notices there is no place to put a received message and
simply returns 0.

I did that and recvmsg() did not return.
--
Gary Jennejohn
Tamas Szakaly
2018-09-10 17:10:53 UTC
Permalink
Post by Gary Jennejohn
On Mon, 10 Sep 2018 10:58:33 +0200
Post by Tamas Szakaly
Hi,
I have a question about the recvmsg syscall. According to POSIX, unless
O_NONBLOCK is set on the socket fd, recvmsg [1] should block until a message
arrives. However, recvmsg returns immediately with 0, if we are trying to
receive a 0-byte message from a SOCK_SEQPACKET AF_UNIX socket. Consider the
#include <stdio.h>
#include <sys/socket.h>
int main(int argc, char** argv) {
int sock[2];
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sock);
struct msghdr msghdr = {0};
int ret = recvmsg(sock[1], &msghdr, 0);
printf("ret=%d, msghdr.msg_flags=0x%08x\n\n", ret, msghdr.msg_flags);
}
[0x00 socketstuff]$ cc socketpair.c -o socketpair && ./socketpair
ret=0, msghdr.msg_flags=0x00000000
You can see that recvmsg returns with 0, even though there were no messages
sent, and neither of the sockets are closed, so it should block indefinitely.
Is this behavior intentional to match the semantics of read [2] (i.e.
attempting to read zero bytes should be a no-op)?
[1] recvmsg: http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
[2] read: http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
You have to initalize msghdr.msg_iov and msghde.iov_len, otherwise
the kernel notices there is no place to put a received message and
simply returns 0.
I did that and recvmsg() did not return.
--
Gary Jennejohn
That's okay, but I want to receive exactly zero bytes. I can send such messages
with sendmsg, and I would like to receive them. Of course I can introduce some
dummy variable to initialize msg_iov and iov_len with, but it will never be
used, and it just feels ugly.
--
Tamas Szakaly
@sghctoma
Loading...