[zeromq-dev] zmq_close() semantics and handling outstanding messages

Martin Lucina mato at kotelna.sk
Thu Jul 8 11:19:51 CEST 2010


On 8/7/2010, "Pieter Hintjens" <ph at imatix.com> wrote:

>On Wed, Jul 7, 2010 at 6:39 PM, Martin Lucina <mato at kotelna.sk> wrote:
>
>> Read up on the manuals for close() and setsockopt().
>>
>> Following the principle of least surprise and consistency with standard
>> sockets, zmq_close() should not be a blocking call by default since
>> close() isn't either.
>
>The standard Linux man pages on close() and setsockopt() are not very
>helpful. Do you have a URL to whatever manual page you're referring
>to?

You're right, the manual pages are confusing. Quoting Stevens, UNIX
Network Programming Vol. 1, 3rd ed., pg., 94, which is a much better
source:

close Function
The normal Unix close function is also used to close a socket and
terminate a TCP connection.
#include <unistd. h>
int close (int sockfd) ;
Returns: 0 if OK, -1 on error
The default action of close with a TCP socket is to mark the socket as
closed and return to the process immediately. The socket descriptor is
no longer usable by the process: It cannot be used as an argument to
read or write. But, TCP will try to send any data that is already queued
to be
sent to the other end, and after this occurs, the normal TCP connection
termination sequence takes place (Section 2.6).
In Section 7.5, we will describe the SO_LINGER socket option, which lets
us change this default action with a TCP socket. In that section, we
will also describe what a TCP application must do to be guaranteed that
the peer application has received any outstanding data.

>[...]

>Further, close() _is_ a blocking call according to the man pages I'm
>looking at (which is why it may return EINTR) though it's unclear
>whether close() flushes data or not.

Almost any UNIX system call can return EINTR if it's interrupted at just
the right time, that doesn't make it a blocking call. close() doesn't
have to wait for anything to happen since it does not make any
guarantees of the state of the operation after it completes (other than
the fd being closed), therefore it's not a blocking call.

>You're comparing TCP sockets with 0MQ sockets but it's not the right
>comparison because send() is working so differently.  What we're doing
>is caching data in application memory and deciding on semantics for
>flushing that cache.  As you said yourself, the accurate comparison is
>between 0MQ sockets and a file system.

The general principle is the same for both a TCP socket and a file, is it
not? close() tells the OS that we're done with this file/socket.
Nowhere at that point do you *expect data loss as a normal consequence
of calling close()*. The file analogy just makes it easier to understand.

>So, does fclose() flush data?  Yes, it does.  Does it do a fsync to
>ensure the data is actually written to disk?  No, that's the OS's
>problem.  It's precisely the same here.

Correct, but as I wrote above, close() flushes data but does not block
until said data ends up anywhere.

-mato



More information about the zeromq-dev mailing list