Maybe before it is sent, iov_len can be defaulted to 0 in the example,
since it'd take an initializer like in c++ to do it otherwise(wanna put c++
in the base! Lol). I assume it wouldn't try to read a zero length iov_base.
The problem may be that usually iov_len has a nonzero value, but the base
points to a bad location, when it isn't specified by the user program.
On Sun, Apr 2, 2017 at 7:05 AM Otto Moerbeek <[email protected]> wrote:

> On Sat, Apr 01, 2017 at 10:57:48AM +0000, Luke Small wrote:
>
> > Or put in the man page to "Google it!" Lol
> > On Sat, Apr 1, 2017 at 5:33 AM Otto Moerbeek <[email protected]> wrote:
> >
> > > On Sat, Apr 01, 2017 at 12:50:46AM -0700, Philip Guenther wrote:
> > >
> > > > On Sat, 1 Apr 2017, Otto Moerbeek wrote:
> > > > > On Sat, Apr 01, 2017 at 01:20:25AM -0500, Luke Small wrote:
> > > > >
> > > > > > Here are two programs. They both fork two clients that try to
> connect
> > > > > > on port 'portno' that is listened to in main(). It spawns a
> receive
> > > > > > that receives passed file descriptors passed from main(). It
> passes a
> > > > > > file descriptor of the client connection to receive twice.
> > > > > > server_sample0.c uses the man page code. server_sample.c uses my
> > > > > > example. the former fails to pass the file descriptor on the
> second
> > > > > > try. the latter succeeds both times. I don't think you have any
> more
> > > > > > questions.
> > > > >
> > > > > Well, it took some effort to get this out of you.
> > > > >
> > > > > It seems that a problem exists indeed. It happens when the iovec
> data
> > > is
> > > > > not filled in, as the example uses. recv(2) only returns the
> number of
> > > > > bytes read from the iovec, so there seems to be some confusion
> about a
> > > > > failed read and a read of zero bytes. I'll check with the standard
> what
> > > > > is supposed to happen when only auciliary data is sent.
> > > >
> > > > Well, it's not a failed read: recvmsg() returns 0, not -1.
> > >
> > > Indeed, my wording was wrong. Still, on the receving side, you like to
> > > dsitinguish beteen -1, 0 (EOF) and a real message, I suppose.
> > >
> > > >
> > > > The issue is that in the kernel socket receive buffer, control
> messages
> > > > from a single send are always followed by a normal data buffer.  In
> > > kernel
> > > > terms, an MT_CONTROL mbuf chain is always followed by an MT_DATA mbuf
> > > > chain...even when there's no data sent.  In that case, the MT_DATA
> mbuf
> > > > has length zero.
> > > >
> > > > This works fine on the sending side, but when recvmsg() finishes
> with the
> > > > control messages and gets to the data buffer, it thinks it's done,
> as the
> > > > caller requested that nothing be copied out and it doesn't remove the
> > > > zero-length MT_DATA mbuf, leaving it at the head of the socket
> buffer.
> > > > Succeeding calls see no control messages at the start and then again
> do
> > > > nothing to the data buffer.
> > > >
> > > > Note this is specific to SOCK_STREAM sockets: the boundary preserving
> > > > behavior of SOCK_DGRAM and SOCK_SEQPACKET mean it doesn't happen
> there.
> > > >
> > > > To avoid this, the application doesn't need to *send* any data, it
> just
> > > > needs to always accept at least one byte of data when calling
> recvmsg().
> > > > Even if there's no data there, that acceptance of more than zero
> bytes of
> > > > data will let recvmsg() peel off the zero-length MT_DATA mbuf from
> the
> > > > send.
> > > >
> > > >
> > > > I guess the questions then are
> > > > 1) is this a bug?  can it be fixed? and
> > > > 2) if not, should it be documented and where?
> > > >
> > > > On the latter, I'm not convinced the example code in CMSG_DATA(3) is
> the
> > > > place to do so.  If we deleted all the EXAMPLES sections from
> manpages
> > > > they should be merely more difficult to understand, not incomplete.
> More
> > > > importantly, this behavior isn't related to the CMSG_* macros at
> all, but
> > > > rather to recvmsg(2) itself.  Maybe a cavest there?
> > >
> > > I'd say, it's a bug, but if it cannot be fixed for some reason,
> > > recvmsg(2) should document this *and* the example in CMSG_DATA(3)
> should
> > > show the proper use.
> > >
> > >
> > >         -Otto
> > >
> > >
>
> Relevant to this discussion (thangs jca@ fro pointing this out!) is
> this old thread:
> http://marc.info/?l=openbsd-tech&m=140008704815878&w=2
>
> The table in one of the messages (look at in raw mode) show that many
> operating systems have problems with this case.
>
> So a CAVEAT entry in recvmsg(2) and the example showing the portable
> way of doings things are still needed, whether the bug will be fixed in
> OpenBSD or not.
>
> As I read it, sendmsg(2) with no data is fine according to the standard:
>
> quote from http://pubs.opengroup.org/onlinepubs/9699919799/ :
>
>         The msg_iov and msg_iovlen fields of message specify zero or more
>         buffers containing the data to be sent. msg_iov points to an array
> of
>         iovec structures; msg_iovlen shall be set to the dimension of this
>         array. In each iovec structure, the iov_base field specifies a
> storage
>         area and the iov_len field gives its size in bytes. Some of these
>         sizes can be zero. The data from each storage area indicated by
>         msg_iov is sent in turn.
>
> Alas, the standard is not clear about a recvmsg(2) call with no data
> buffer space.
>
>         -Otto
>

Reply via email to