From: "Lavrentiev, Anton (NIH/NLM/NCBI) [C] via cygwin" <cygwin@cygwin.com>
To: "'cygwin@cygwin.com'" <cygwin@cygwin.com>
Subject: SOCK_NONBLOCK not honored
Date: Thu, 01 Nov 2018 20:56:00 -0000 [thread overview]
Message-ID: <SN6PR09MB3247DE8659997EDB93309403A5CE0@SN6PR09MB3247.namprd09.prod.outlook.com> (raw)
Hi,
Looks like CYGWIN defines but does not honor the SOCK_NONBLOCK flag when used with socket(2).
(It also defines SOCK_CLOEXEC but I haven't checked whether it is honored -- full disclosure.)
Consider the following code:
$ cat bug.c
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#ifdef BUG
# define SOCK_TYPE (SOCK_STREAM | SOCK_NONBLOCK)
#else
# define SOCK_TYPE SOCK_STREAM
#endif
int main()
{
char buf[80];
ssize_t n;
struct sockaddr_in in;
int s = socket(AF_INET, SOCK_TYPE, 0);
#ifndef BUG
fcntl(s, F_SETFL, O_NONBLOCK);
#endif
memset(&in, 0, sizeof(in));
in.sin_family = AF_INET;
in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
in.sin_port = htons(6666);
if (connect(s, (struct sockaddr*) &in, sizeof(in)) < 0) {
int err;
socklen_t len = sizeof(err);
struct pollfd pfd;
if (errno != EINPROGRESS) {
printf("connect failed immediately: %m\n");
return 1;
}
memset(&pfd, 0, sizeof(pfd));
pfd.fd = s;
pfd.events = POLLOUT;
if (!poll(&pfd, 1, 1000)) {
printf("poll timed-out\n");
return 2;
}
if (pfd.revents & (POLLERR | POLLHUP)) {
printf("poll failed 0x%04X\n", pfd.revents);
return 3;
}
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void*) &err, &len) != 0) {
printf("getsockopt failed: %m\n");
return 4;
}
if (err != 0) {
printf("connect failed: %s\n", strerror(err));
return 5;
}
}
errno = 0;
n = recv(s, buf, sizeof(buf), 0);
printf("Got %zd byte(s): %m\n", n);
return 0;
}
When the program is built on Linux with and without the macro BUG defined, the result is all the same,
the last recv() correctly finishes with -1 and EAGAIN (run "nc -l 6666" as a server).
$ gcc -Wall -o bug bug.c
$ ./bug
Got -1 byte(s): Resource temporarily unavailable
$ gcc -Wall -DBUG -o bug bug.c
$ ./bug
Got -1 byte(s): Resource temporarily unavailable
However, on CYGWIN when the code is compiled with -DBUG, the last recv() becomes blocking, and the program never exits:
$ gcc -Wall -o bug bug.c
$ ./bug
Got -1 byte(s): Resource temporarily unavailable
$ gcc -Wall -DBUG -o bug bug.c
$ ./bug
...
strace confirms that the recv() has blocked the execution. Also, connect() appears to be blocking, too, but it's harder to see.
Thanks,
Anton Lavrentiev
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
next reply other threads:[~2018-11-01 20:56 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-01 20:56 Lavrentiev, Anton (NIH/NLM/NCBI) [C] via cygwin [this message]
2018-11-05 20:05 ` Corinna Vinschen
2018-11-06 9:29 ` Marco Atzeri
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=SN6PR09MB3247DE8659997EDB93309403A5CE0@SN6PR09MB3247.namprd09.prod.outlook.com \
--to=cygwin@cygwin.com \
--cc=lavr@ncbi.nlm.nih.gov \
/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).