Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-29 Thread Samuel Thibault
Richard Braun, le Sat 28 Jun 2014 12:42:40 +0200, a écrit :
> However, I'm not sure I understand why other users would rely on a
> stream protocol for tokens.

Right. I'd say we can keep with this for now.

Samuel


-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: 
https://lists.debian.org/20140629175112.gf6...@type.youpi.perso.aquilenet.fr



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Roland McGrath
I'm inclined to say libc is not the right place to fix this.  If the user
says write/send 0, what that means should be up to the io server to
decide--even if all the servers we have today are intending to implement
the same POSIX semantics.


-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: 
https://lists.debian.org/20140628190551.308052c3...@topped-with-meat.com



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Andreas Cadhalpun

Hi Richard,

On 28.06.2014 10:48, Richard Braun wrote:

Thanks for the report. There are actually two sides of the problem.
First, I agree that there seems to be a bug, but let's take a closer
look at the spec. The return value for recv() is defined as :

"Upon successful completion, recv() shall return the length of the
message in bytes. If no messages are available to be received and the
peer has performed an orderly shutdown, recv() shall return 0."

This doesn't creates a strict equivalence between "orderly shutdown" and
"shall return 0". But in practice, this seems to be the actual
assumption, so let's say that there is indeed a Hurd bug here. By the
way, although the send() and recv() functions themselves (in glibc) may
benefit from additions to filter out empty messages (at least send()),
the server functions are those found in pflocal concerning AF_UNIX
sockets.

But there is also a bug in the client code, IMO. Here is how send() is
specified :

"The length of the message to be sent is specified by the length
argument.

[...]

If the socket argument refers to a socket and the flags argument is 0,
the send() function is equivalent to write()."

And here is write() :

"If nbyte is zero and the file is not a regular file, the results are
unspecified."

We might also want to change this though, since the behaviour observed
on other systems seems more appropriate.


Thanks for looking into this.
Indeed, according to the specification, the behavior is unspecified. 
(Which IMHO is a bug in the specification.)

But the specification also says:
"Before any action described below is taken, and if nbyte is zero and 
the file is a regular file, the write() function may detect and return 
errors as described below. In the absence of errors, or if error 
detection is not performed, the write() function shall return zero and 
have no other results."


This holds only for regular files, but the principle of least surprise 
suggests that it should also hold for special files, if that is possible.


On 28.06.2014 11:51, Richard Braun wrote:
> I've committed a fix upstream [1], please see if it solves your issues
> as well.

I tried this patch and with it applied both the example program and 
clamd/clamdscan work as they should.

But I can't comment on Samuel's objections to the patch.

Best regards,
Andreas


--
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: https://lists.debian.org/53aef770.6060...@googlemail.com



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 28, 2014 at 12:42:40PM +0200, Richard Braun wrote:
> I'll see if simply catching completely empty messages at socket_send is
> a good enough solution.

The solution seems to work, and I couldn't see anything against it,
unlike the previous attempt. However I'd really like to put it into
libpipe as I don't see any need, but only potential problems, for empty
data packets. I'll wait for your reply before taking action.

-- 
Richard Braun


-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: https://lists.debian.org/20140628125242.ga10...@dalaran.sceen.net



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 28, 2014 at 12:09:15PM +0200, Samuel Thibault wrote:
> Richard Braun, le Sat 28 Jun 2014 11:51:42 +0200, a écrit :
> > On Sat, Jun 28, 2014 at 10:48:56AM +0200, Richard Braun wrote:
> > > On Sat, Jun 21, 2014 at 03:56:46PM +0200, Andreas Cadhalpun wrote:
> > > > This is because the client is calling:
> > > > send(sockfd, "", 0, 0)
> > > > 
> > > > Normally this doesn't trigger recv() in the server and thus can be
> > > > used to test, whether the socket is working.
> > > > But on Hurd it actually sends an empty message, so that the real
> > > > message, which is sent later, is not received.
> > 
> > I've committed a fix upstream [1], please see if it solves your issues
> > as well.
> > 
> > [1] 
> > http://git.savannah.gnu.org/cgit/hurd/hurd.git/commit/?id=6f856c62613ffc82bf3572a372d2851638c2fb90
> 
> Mmm, I'm not sure we want to fix it in libpipe: other users of libpipe
> may want to pass empty messages (e.g. as mere tokens). Strictly
> speaking, it could be fixed in glibc's send() function. It however makes
> sense to me to fix it at the socket RPC protocol, i.e. in pflocal's
> S_socket_send.

In addition, I just noticed that passing control data relies on always
passing regular data, so this needs to be fixed too. However, I'm not
sure I understand why other users would rely on a stream protocol for
tokens. This would merely result in spurious wakeups, and AIUI, control
data is meant exactly for that purpose.

I'll see if simply catching completely empty messages at socket_send is
a good enough solution.

-- 
Richard Braun


-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: https://lists.debian.org/20140628104240.ga16...@dalaran.sceen.net



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Samuel Thibault
Richard Braun, le Sat 28 Jun 2014 11:51:42 +0200, a écrit :
> On Sat, Jun 28, 2014 at 10:48:56AM +0200, Richard Braun wrote:
> > On Sat, Jun 21, 2014 at 03:56:46PM +0200, Andreas Cadhalpun wrote:
> > > This is because the client is calling:
> > >   send(sockfd, "", 0, 0)
> > > 
> > > Normally this doesn't trigger recv() in the server and thus can be
> > > used to test, whether the socket is working.
> > > But on Hurd it actually sends an empty message, so that the real
> > > message, which is sent later, is not received.
> 
> I've committed a fix upstream [1], please see if it solves your issues
> as well.
> 
> [1] 
> http://git.savannah.gnu.org/cgit/hurd/hurd.git/commit/?id=6f856c62613ffc82bf3572a372d2851638c2fb90

Mmm, I'm not sure we want to fix it in libpipe: other users of libpipe
may want to pass empty messages (e.g. as mere tokens). Strictly
speaking, it could be fixed in glibc's send() function. It however makes
sense to me to fix it at the socket RPC protocol, i.e. in pflocal's
S_socket_send.

Samuel


-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: 
https://lists.debian.org/20140628100915.gz6...@type.youpi.perso.aquilenet.fr



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 28, 2014 at 10:48:56AM +0200, Richard Braun wrote:
> On Sat, Jun 21, 2014 at 03:56:46PM +0200, Andreas Cadhalpun wrote:
> > This is because the client is calling:
> > send(sockfd, "", 0, 0)
> > 
> > Normally this doesn't trigger recv() in the server and thus can be
> > used to test, whether the socket is working.
> > But on Hurd it actually sends an empty message, so that the real
> > message, which is sent later, is not received.
> 
> Hello,
> 
> Thanks for the report. There are actually two sides of the problem.
> First, I agree that there seems to be a bug, but let's take a closer

I've committed a fix upstream [1], please see if it solves your issues
as well.

-- 
Richard Braun

[1] 
http://git.savannah.gnu.org/cgit/hurd/hurd.git/commit/?id=6f856c62613ffc82bf3572a372d2851638c2fb90


-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: https://lists.debian.org/20140628095142.ga7...@dalaran.sceen.net



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 21, 2014 at 03:56:46PM +0200, Andreas Cadhalpun wrote:
> This is because the client is calling:
>   send(sockfd, "", 0, 0)
> 
> Normally this doesn't trigger recv() in the server and thus can be
> used to test, whether the socket is working.
> But on Hurd it actually sends an empty message, so that the real
> message, which is sent later, is not received.

Hello,

Thanks for the report. There are actually two sides of the problem.
First, I agree that there seems to be a bug, but let's take a closer
look at the spec. The return value for recv() is defined as :

"Upon successful completion, recv() shall return the length of the
message in bytes. If no messages are available to be received and the
peer has performed an orderly shutdown, recv() shall return 0."

This doesn't creates a strict equivalence between "orderly shutdown" and
"shall return 0". But in practice, this seems to be the actual
assumption, so let's say that there is indeed a Hurd bug here. By the
way, although the send() and recv() functions themselves (in glibc) may
benefit from additions to filter out empty messages (at least send()),
the server functions are those found in pflocal concerning AF_UNIX
sockets.

But there is also a bug in the client code, IMO. Here is how send() is
specified :

"The length of the message to be sent is specified by the length
argument.

[...]

If the socket argument refers to a socket and the flags argument is 0,
the send() function is equivalent to write()."

And here is write() :

"If nbyte is zero and the file is not a regular file, the results are
unspecified."

We might also want to change this though, since the behaviour observed
on other systems seems more appropriate.

-- 
Richard Braun


-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: https://lists.debian.org/20140628084856.ga24...@dalaran.sceen.net



Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-21 Thread Andreas Cadhalpun

Package: libc0.3
Version: 2.19-3
Severity: normal
X-Debbugs-CC: debian-h...@lists.debian.org

Dear Maintainer,

it seems send() on Hurd doesn't work like it does everywhere else.

Attached is a simple test case.
To reproduce the problem, execute make in a folder with the attached 
client.c, server.c and Makefile.

Then run ./server, open another terminal and run ./client.

The usual output is:
$ ./server
Message: 'TEST'

$ ./client
Socket works.
Answer: 'ANSWER'

But on Hurd one gets:
$ ./server
Message: ''

$ ./client
Socket works.
Answer: 'ANSWER'

This is because the client is calling:
send(sockfd, "", 0, 0)

Normally this doesn't trigger recv() in the server and thus can be used 
to test, whether the socket is working.
But on Hurd it actually sends an empty message, so that the real 
message, which is sent later, is not received.


As a workaround, one can comment out this test, which is done in the 
server, so that the ANSWER reaches the client.


This should be handled on Hurd in the same way as on other platforms.

I noticed this bug, because it breaks the communication between clamd 
and clamdscan on Hurd, thus leading to test failures and ultimately a FTBFS.


Best regards,
Andreas


-- System Information:
Debian Release: jessie/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: hurd-i386 (i686-AT386)

Kernel: GNU-Mach 1.4-486/Hurd-0.5
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash

Versions of packages libc0.3 depends on:
ii  hurd-libs0.3  1:0.5.git20140526-2
ii  libgcc1   1:4.9.0-7

Versions of packages libc0.3 recommends:
pn  libc0.3-i686  

Versions of packages libc0.3 suggests:
ii  debconf [debconf-2.0]  1.5.53
pn  glibc-doc  
#include 
#include 
#include 
#include 
#include 

char sock_name[] = "TEST.ctl";

int connect_socket()
{
	struct sockaddr_un server;
	int sockfd;

	memset(&server, 0, sizeof(server));
	server.sun_family = AF_UNIX;
	strncpy(server.sun_path, sock_name, sizeof(server.sun_path));
	server.sun_path[sizeof(server.sun_path) - 1] = '\0';

	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

	if (sockfd < 0) {
		printf("Can't create socket %s: %s\n", sock_name, strerror(errno));
		return -1;
	}

	if (connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
		printf("Can't connect to socket %s: %s\n", sock_name, strerror(errno));
		close(sockfd);
		return -2;
	}

	return sockfd;
}

int main()
{
	char buff[20];
	int sockfd = connect_socket();
	if (sockfd < 0) {
		return sockfd;
	}

	if (send(sockfd, "", 0, 0) < 0) {
		printf("Socket not working: %s\n", strerror(errno));
	} else {
		printf("Socket works.\n");
	}

	if (send(sockfd, "TEST", 4, 0) < 0) {
		printf("Could not write to socket: %s\n", strerror(errno));
		close(sockfd);
		return 1;
	}

	memset(buff, 0, sizeof (buff));
	if (recv(sockfd, buff, sizeof (buff), 0) < 0) {
		printf("Error receiving answer: %s\n", strerror(errno));
		close(sockfd);
		return 2;
	}
	printf("Answer: '%s'\n", buff);
	close(sockfd);
	return 0;
}
#! /usr/bin/make -f

CC ?= gcc
CFLAGS ?= -g -pedantic -Wall -Wextra

all: server client


%:
$(CC) $(CFLAGS) $@.c -o $@
#include 
#include 
#include 
#include 
#include 

char sock_name[] = "TEST.ctl";

int create_socket()
{
	struct sockaddr_un server;
	int sockfd;

	memset(&server, 0, sizeof(server));
	server.sun_family = AF_UNIX;
	strncpy(server.sun_path, sock_name, sizeof(server.sun_path));
	server.sun_path[sizeof(server.sun_path) - 1] = '\0';

	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

	if (sockfd < 0) {
		printf("Can't create socket %s: %s\n", sock_name, strerror(errno));
		return -1;
	}

	if (bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
		printf("Socket file %s could not be bound: %s\n", server.sun_path, strerror(errno));
		close(sockfd);
		return -2;
	}

	if (listen(sockfd, 20) < 0) {
		printf("listen() error: %s\n", strerror(errno));
		close(sockfd);
		return -3;
	}

	return sockfd;
}

int main()
{
	int ret, con;
	char buff[20];
	int sockfd = create_socket();
	if (sockfd < 0) {
		return sockfd;
	}

	con = accept(sockfd, 0, 0);

	memset(buff, 0, sizeof(buff));
	if (recv(con, buff, sizeof (buff), 0) >= 0) {
		printf("Message: '%s'\n", buff);
	}
/*
	if (write(con, "", 0) < 0) {
		printf("Socket not working: %s\n", strerror(errno));
		return 1;
	} else {
		printf("Socket works.\n");
	}
 */
	if (write(con, "ANSWER", 6) < 0) {
		printf("Could not write to socket: %s\n", strerror(errno));
		ret = 2;
	}

	close(con);

	if (unlink(sock_name) == -1) {
		printf("Socket file %s could not be removed: %s\n", sock_name, strerror(errno));
		ret = 3;
	}
	close(sockfd);
	return ret;
}