public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: <sten.kristian.ivarsson@gmail.com>
To: "'Ken Brown'" <kbrown@cornell.edu>, <cygwin@cygwin.com>
Subject: RE: AF_UNIX/SOCK_DGRAM is dropping messages
Date: Thu, 8 Apr 2021 10:37:29 +0200	[thread overview]
Message-ID: <002101d72c52$695ea630$3c1bf290$@gmail.com> (raw)
In-Reply-To: <134074c1-4c0b-0842-b88b-536a1ed4aefe@cornell.edu>

[-- Attachment #1: Type: text/plain, Size: 4081 bytes --]

> >>>>>>>> Using AF_UNIX/SOCK_DGRAM with current version (3.2.0) seems
> to
> >>>>>>>> drop messages or at least they are not received in the same
> >>>>>>>> order they are  sent
> >>>>
> >>>> [snip]
> >>>>
> >>>>> Thanks for the test case.  I can confirm the problem.  I'm not
> >>>>> familiar enough with the current AF_UNIX implementation to debug
> >>>>> this easily.  I'd rather spend my time on the new implementation
> >>>>> (on the topic/af_unix branch).  It turns out that your test case
> >>>>> fails there too, but in a completely different way, due to a bug
> >>>>> in sendto for datagrams.  I'll see if I can fix that bug and then try again.
> >>>>>
> >>>>> Ken
> >>>>
> >>>> Ok, too bad it wasn't our own code base but good that the "mystery"
> >>>> is verified
> >>>>
> >>>> I finally succeed to build topic/af_unix (after finding out what
> >>>> version of zlib was needed), but not with -D__WITH_AF_UNIX to
> >>>> CXXFLAGS though and thus I haven’t tested it yet
> >>>>
> >>>> Is it sufficient to add the define to the "main" Makefile or do you
> >>>> have to add it to all the Makefile:s ? I guess I can find out
> >>>> though
> >>>
> >>> I do it on the configure line, like this:
> >>>
> >>>    ../af_unix/configure CXXFLAGS="-g -O0 -D__WITH_AF_UNIX" --
> prefix=...
> >>>
> >>>> Is topic/af_unix fairly up to date with master branch ?
> >>>
> >>> Yes, I periodically cherry-pick commits from master to topic/af_unix.
> >>> I'lldo that again right now.
> >>>
> >>>> Either way, I'll be glad to help out testing topic/af_unix
> >>>
> >>> Thanks!
> >>
> >> I've now pushed a fix for that sendto bug, and your test case runs
> >> without error on the topic/af_unix branch.
> >
> > It seems like the test-case do work now with topic/af_unix in blocking
> > mode, but when using non-blocking (with MSG_DONTWAIT) there are
> some
> > issues I think
> >
> > 1. When the queue is empty with non-blocking recv(), errno is set to
> > EPIPE but I think it should be EAGAIN (or maybe the pipe is getting
> > broken for real of some reason ?)
> >
> > 2. When using non-blocking recv() and no message is written at all, it
> > seems like recv() blocks forever
> >
> > 3. Using non-blocking recv() where the "client" does send less than
> > "count" messages, sometimes recv() blocks forever (as well)
> >
> >
> > My naïve analysis of this is that for the first issue (if any) the
> > wrong errno is set and for the second issue it blocks if no sendto()
> > is done after the first recv(), i.e. nothing kicks the "reader thread"
> > in the butt to realise the queue is empty. It is not super clear
> > though what POSIX says about creating blocking descriptors and then
> > using non-blocking-flags with recv(), but this works in Linux any way
> 
> The explanation is actually much simpler.  In the recv code where a bound
> datagram socket waits for a remote socket to connect to the pipe, I simply
> forget to handle MSG_DONTWAIT.  I've pushed a fix.  Please retest.

I tested it and now it seems like we get EAGAIN when there's no msg on the queue, but it seems like the client is blocked as well and that it cannot write any more messages until it is consumed by the server, so the af_unix.cpp test-client end prematurely

If using sendto() with MSG_DONTWAIT as well, that is getting a EAGAIN, but the socket in it self is not a non-blocking socket, it is just the recv() that is done in a non-blocking fashion

As I said earlier, it's a bit fuzzy (or at least for me) what POSIX mean by non/blocking descriptors combined with non/blocking operations, but as far as I understand, it should be possible to use blocking sendto()and messages should be written (as long as some buffer is not filled) at the same time someone is doing non-blocking recv()

What is your take on this ?

> I should add that in all my work so far on the topic/af_unix branch, I've
> thought mainly about stream sockets.  So there may still be things remaining
> to be implemented for the datagram case.
> 
> Ken

[-- Attachment #2: af_unix.cpp --]
[-- Type: text/plain, Size: 2737 bytes --]

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

#undef AF_UNIX
#define AF_UNIX 31

#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <thread>
#include <chrono>


// $ g++ --std=gnu++17 af_unix.cpp

const char* const path = "address";
const int count = 10;
const int size = BUFSIZ * 1;

int client()
{
    const int fd = socket( AF_UNIX, SOCK_DGRAM, 0);

    if( fd == -1)
    {
        perror( "socket error");
        return -1;
    }

    struct sockaddr_un address{};

    strcpy( address.sun_path, path);
    address.sun_family = AF_UNIX;

    char buffer[size] = {};

    for( int idx = 0; idx < count; ++idx)
    {
        memcpy( buffer, &idx, sizeof idx);

        fprintf( stdout, "client idx: %d\n", idx);
    
        const ssize_t result = sendto( fd, buffer, size, 0, (struct sockaddr*)&address, sizeof address);

        // Assume the whole chunk can be sent
        if( result != size)
        {
            perror( "sendto error");
            return -1;
        }
    }

    close( fd);
    return 0;
}

int server()
{
    const int fd = socket( AF_UNIX, SOCK_DGRAM, 0);

    if( fd == -1)
    {
        perror( "socket error");
        return -1;
    }

    struct sockaddr_un address{};

    strcpy( address.sun_path, path);
    address.sun_family = AF_UNIX;

    const int result = bind( fd, (struct sockaddr*)&address, sizeof address);

    if( result == -1)
    {
        perror( "bind error");
        return -1;
    }

    return fd;
}

int main( int argc, char* argv[])
{
    const int fd = server( );

    if( fd != -1)
    {
        fprintf( stdout, "%d\tnumber of packages\n", count);
        fprintf( stdout, "%d\tbytes per package\n", size);

        std::thread{ [&](){client( );}}.detach();

        std::this_thread::sleep_for( std::chrono::microseconds( 250));
    
        char buffer[size] = {};

        for( int idx = 0; idx < count; ++idx)
        {
            fprintf( stdout, "server idx: %d\n", idx);

            const ssize_t result = recv( fd, buffer, size, MSG_DONTWAIT);

            // Assume the whole chunk can be read
            if( result != size)
            {
                perror("recv error");
                unlink( path);
                return -1;
            }

            int index = 0;
            memcpy( &index, buffer, sizeof idx);

            if( index != idx)
            {
                fprintf( stderr, "expected %d but got %d\n", idx, index);
                unlink( path);
                return -1;
            }
        }

        close( fd);
        unlink( path);
    }

    return 0;
}

  reply	other threads:[~2021-04-08  8:37 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-23 15:37 sten.kristian.ivarsson
2021-03-23 19:20 ` Glenn Strauss
2021-03-24  9:18   ` sten.kristian.ivarsson
2021-03-30 14:17     ` Ken Brown
2021-03-31  8:24       ` sten.kristian.ivarsson
2021-03-31 15:07         ` Ken Brown
2021-04-01 16:02           ` Ken Brown
2021-04-06  7:52             ` Noel Grandin
2021-04-06 14:59               ` Ken Brown
2021-04-06 14:50             ` sten.kristian.ivarsson
2021-04-06 15:24               ` Ken Brown
2021-04-07 14:56               ` Ken Brown
2021-04-08  8:37                 ` sten.kristian.ivarsson [this message]
2021-04-08 19:47                   ` sten.kristian.ivarsson
2021-04-08 21:02                     ` Ken Brown
2021-04-13 14:06                 ` sten.kristian.ivarsson
2021-04-13 14:47                   ` Ken Brown
2021-04-13 22:43                     ` Ken Brown
2021-04-14 15:53                       ` Ken Brown
2021-04-14 17:14                       ` sten.kristian.ivarsson
2021-04-14 21:58                         ` Ken Brown
2021-04-15 13:15                           ` sten.kristian.ivarsson
2021-04-15 15:01                             ` Ken Brown
2021-04-27 14:56                               ` Ken Brown
2021-04-28  7:15                                 ` sten.kristian.ivarsson
2021-08-12 12:56                                   ` sten.kristian.ivarsson
2021-08-13 11:19                                     ` Ken Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='002101d72c52$695ea630$3c1bf290$@gmail.com' \
    --to=sten.kristian.ivarsson@gmail.com \
    --cc=cygwin@cygwin.com \
    --cc=kbrown@cornell.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).