public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
From: Ken Brown <kbrown@cornell.edu>
To: cygwin-patches@cygwin.com
Subject: Re: [PATCH 0/1] Fix MSG_WAITALL support
Date: Mon, 12 Oct 2020 14:43:09 -0400	[thread overview]
Message-ID: <d582c3d6-bd0c-f2c7-9fbc-38edb3511cdf@cornell.edu> (raw)
In-Reply-To: <20201012180213.21748-1-kbrown@cornell.edu>

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

On 10/12/2020 2:02 PM, Ken Brown via Cygwin-patches wrote:
> It looks to me like there's been a bug in the MSG_WAITALL support for
> AF_INET and AF_LOCAL sockets ever since that support was first
> introduced 13 years ago in commit 023a2fa7.  If I'm right, MSG_WAITALL
> has never worked.
> 
> This patch fixes it.  I'll push it in a few days if no one sees
> anything wrong with it.
> 
> In a followup email I'll show how I tested it.

Attached are slight variants of the server/client programs from Section 57.2 of 
Kerrisk's book, "The Linux Programming Interface".  The only essential 
difference is that I've changed the server program to (a) use a small buffer 
(size 10 instead of 100) and (b) use 'recv' with the MSG_WAITALL flag instead of 
'read'.  The 'recv' call shouldn't return until it reads 10 bytes.

To test, run waitall_sv in one terminal and waitall_cl in a second.  Type 
something in the second terminal (followed by RET), and it should be echoed in 
the first.  But because of the MSG_WAITALL flag, the echoing shouldn't occur 
until 10 bytes have been written.  For example, if I type "abcd<RET>" in the 
second terminal and then do it again, I should see the following:

# Terminal 2:
$ ./waitall_cl
abcd
abcd

# Terminal 1:
$ ./waitall_sv
abcd
abcd

Here the echoing in Terminal 1 shouldn't occur until I've typed both "abcd" 
lines in Terminal 2.

[Note that there is a newline character after each "abcd", so "abcd<RET>" is 5 
bytes long, and the two lines together are 10 bytes long.]

Before I apply my patch, each line typed in Terminal 2 is immediately echoed in 
Terminal 1.  After I apply the patch, the echoing doesn't occur until I've typed 
both lines.

Ken

[-- Attachment #2: waitall_sv.c --]
[-- Type: text/plain, Size: 1461 bytes --]

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/socket.h>

#define SV_SOCK_PATH "/tmp/waitall"

#define BUF_SIZE 10

#define BACKLOG 5

int
main ()
{
    struct sockaddr_un addr;
    int sfd, cfd;
    ssize_t nread;
    char buf[BUF_SIZE];

    if ((sfd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
      {
	perror ("socket");
	exit (1);
      }
    if (remove (SV_SOCK_PATH) < 0 && errno != ENOENT)
      {
	perror ("remove");
        exit (1);
      }

    memset (&addr, 0, sizeof (struct sockaddr_un));
    addr.sun_family = AF_UNIX;
    strncpy (addr.sun_path, SV_SOCK_PATH, sizeof (addr.sun_path) - 1);

    if (bind (sfd, (struct sockaddr *) &addr, sizeof (struct sockaddr_un)) < 0)
      {
	perror ("bind");
	exit (1);
      }

    if (listen (sfd, BACKLOG) < 0)
      {
        perror ("listen");
	exit (1);
      }

    while (1)
      {
        cfd = accept (sfd, NULL, NULL);
        if (cfd < 0)
	  {
            perror ("accept");
	    exit (1);
	  }

        /* Transfer data from connected socket to stdout until EOF. */
        while ((nread = recv (cfd, buf, BUF_SIZE, MSG_WAITALL)) > 0)
	  if (write (STDOUT_FILENO, buf, nread) != nread)
	    {
	      perror ("partial/failed write");
	      exit (1);
	    }

        if (nread < 0)
	  {
            perror ("read");
	    exit (1);
	  }

        if (close (cfd) < 0)
	  {
            perror ("close");
	    exit (1);
	  }
      }
}

[-- Attachment #3: waitall_cl.c --]
[-- Type: text/plain, Size: 944 bytes --]

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/socket.h>

#define SV_SOCK_PATH "/tmp/waitall"

#define BUF_SIZE 100

int
main ()
{
    struct sockaddr_un addr;
    int sfd;
    ssize_t nread;
    char buf[BUF_SIZE];

    if ((sfd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
      {
	perror ("socket");
	exit (1);
      }

    memset (&addr, 0, sizeof(struct sockaddr_un));
    addr.sun_family = AF_UNIX;
    strncpy (addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1);

    if (connect (sfd, (struct sockaddr *) &addr,
		sizeof (struct sockaddr_un)) < 0)
      {
        perror ("connect");
	exit (1);
      }

    /* Copy stdin to socket. */
    while ((nread = read (STDIN_FILENO, buf, BUF_SIZE)) > 0)
      if (write (sfd, buf, nread) != nread)
	{
	  perror ("partial/failed write");
	  exit (1);
	}

    if (nread < 0)
      {
        perror ("read");
	exit (1);
      }
}

  parent reply	other threads:[~2020-10-12 18:43 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-12 18:02 Ken Brown
2020-10-12 18:02 ` [PATCH 1/1] Cygwin: AF_INET and AF_LOCAL: recv_internal: fix " Ken Brown
2020-10-12 18:43 ` Ken Brown [this message]
2020-10-22 19:26 ` [PATCH 0/1] Fix " Ken Brown
2020-10-23  9:21   ` Corinna Vinschen

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=d582c3d6-bd0c-f2c7-9fbc-38edb3511cdf@cornell.edu \
    --to=kbrown@cornell.edu \
    --cc=cygwin-patches@cygwin.com \
    /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).