Bug 75371

Summary: recvmmsg() timeout misbehavior
Product: Networking Reporter: Michael Kerrisk (mtk.manpages)
Component: OtherAssignee: Stephen Hemminger (stephen)
Status: NEW ---    
Severity: normal CC: jezz, lovelylich, szg00000
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 3.15-rc Subsystem:
Regression: No Bisected commit-id:

Description Michael Kerrisk 2014-05-03 10:22:34 UTC
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
                    unsigned int flags, struct timespec *timeout);

As currently implemented, the recvmmsg() timeout feature appears to be fit for no sane use. The timeout argument is implemented as follows:


    Timer is armed at the time of the call

    while (datagrams-received < vlen) {

         Wait for the next datagram

         Check if timeout has been exceeded; if yes, break out of loop
    }

Since the timeout is only checked after the arrival of each datagram,
we can have scenarios like the following:

0. Assume a timeout of 10 (T) seconds, that vlen is 5, and the call 
   is made at time X
1. First datagram arrives at time X+2.
2. Second datagram arrives at time X+4 secs
3. Third datagram arrives at time X+6 secs
4. No more datagrams arrive.

In this case, the call blocks forever. It hardly seems that this could be intended behavior. The problem, of course is that the timeout is checked only after receipt of a datagram.

Basically, if up to vlen-1 datagrams arrive before X+T, but then no more datagrams arrive, the call will remain blocked forever. If it's intended behavior (seems unlikely), the rationale needs elaborate so that it can be documented in the man page. If not, a fix seems to be needed, since otherwise, it's hard to see how the recvmmsg() timeout argument
can sanely be used.

See also http://thread.gmane.org/gmane.linux.man/5677
Comment 1 Jérôme Pouiller 2015-03-04 10:19:04 UTC
It is possible to work around this bug using SO_RCVTIMEO (described in socket(7)) in add of timeout parameter of recvmmsg. 

Thus, recvmmsg will exit if no data was received since SO_RCVTIMEO or after timeout. In worst case, recvmmsg will exit after timeout + SO_RCVTIMEO (in case described by Michael Kerrisk).