[prev in list] [next in list] [prev in thread] [next in thread]
List: freebsd-hackers
Subject: Re: Interpretation of POSIX.1-2008 for recvmsg
From: Marcin Cieslak <saper () saper ! info>
Date: 2015-07-31 23:59:00
Message-ID: alpine.BSF.2.11.1507312335080.7491 () z ! fncre ! vasb
[Download RAW message or body]
On Fri, 31 Jul 2015, Patrick Mooney wrote:
> Greetings,
> I have been researching differences in recvmsg() behavior across platforms
> (namely Illumos and Linux) with respect to MSG_PEEK and 0-length buffers.
> Certain Linux software I am attempting to run under Illumos makes a recvmsg()
> call with a 0-length iovec and flags set to MSG_PEEK in order to interrogate
> the size of a queued dgram. On native Linux, recvmsg() returns the size of the
> queued dgram (with the MSG_TRUNC flag set). On both Illumos and FreeBSD, a
> size of 0 is returned (with MSG_TRUNC set as well). In reading the POSIX spec
> (http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html), it is
> not clear that returning 0 in this case is correct behavior.
>
> Here is a small test program I wrote up to display the differences in behavior:
> https://us-east.manta.joyent.com/patrick.mooney/public/recvmsg/peektest.c
>
> The output on Linux:
> peek len: 20 errno: 0 flags: 20
> recv len: 20 errno: 0 flags: 0
> ... versus BSD and Illumos:
> peek len: 0 errno: 2 flags: 12
> recv len: 20 errno: 2 flags: 0
errno does not has to be reset to 0 to indicate
success. You should check return value < 0 before using errno.
I set errno to 0 before invoking recvmsg() and
it stays 0 (that means it is just not modified).
Also setting MSG_TRUNC in the input flags is not specified
by POSIX (use just MSG_PEEK). MSG_TRUNC is the output flag.
What you are expecting is the non-standard Linux
behaviour with this flag set as input:
MSG_TRUNC (since Linux 2.2)
For raw (AF_PACKET), Internet datagram (since Linux 2.4.27/2.6.8), \
netlink (since Linux 2.6.22) and UNIX datagram (since Linux
3.4) sockets: return the real length of the packet or datagram, even \
when it was longer than the passed buffer. Not implemented for UNIX domain \
(unix(7)) sockets.
Be aware that recvmsg(x, y, MSG_PEEK) *also* reads data -
so Solaris and BSD consitently return what was saved
into the buffer.
In short - to check how large the message is, supply the buffer
that is large enough (or try MSG_PEEK until it is large enough).
Here are the result of my modified peektest.c[1]:
peek buflen: 0x02
peek len: 0x02 errno: 0 flags: 0x12
peek read: [AB ]
read buflen: 0x20
recv len: 0x20 errno: 0 flags: 0x00
recv read: [ABCD]
On Linux:
Using port 18399
peek buflen: 0x02
peek len: 0x02 errno: 0 flags: 0x20
peek read: [AB ]
read buflen: 0x20
recv len: 0x20 errno: 0 flags: 0x00
recv read: [ABCD]
MSG_TRUNC in the input flags is not POSIX.
//Marcin
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic