lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1282785886.22839.199.camel@localhost>
Date:	Thu, 26 Aug 2010 02:24:46 +0100
From:	Ben Hutchings <bhutchings@...arflare.com>
To:	David Miller <davem@...emloft.net>
Cc:	kosaki.motohiro@...fujitsu.com, netdev@...r.kernel.org,
	linux-kernel@...r.kernel.org, yoshfuji@...ux-ipv6.org
Subject: Re: [PATCH] tcp: select(writefds) don't hang up when a peer close
 connection

On Wed, 2010-08-25 at 15:34 -0700, David Miller wrote:
> From: KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>
> Date: Wed, 25 Aug 2010 11:05:48 +0900 (JST)
> 
> > This issue come from ruby language community. Below test program
> > hang up when only run on Linux.
> > 
> > 	% uname -mrsv
> > 	Linux 2.6.26-2-486 #1 Sat Dec 26 08:37:39 UTC 2009 i686
> > 	% ruby -rsocket -ve '
> > 	BasicSocket.do_not_reverse_lookup = true
> > 	serv = TCPServer.open("127.0.0.1", 0)
> > 	s1 = TCPSocket.open("127.0.0.1", serv.addr[1])
> > 	s2 = serv.accept
> > 	s2.close
> > 	s1.write("a") rescue p $!
> > 	s1.write("a") rescue p $!
> > 	Thread.new {
> > 	  s1.write("a")
> > 	}.join'
> > 	ruby 1.9.3dev (2010-07-06 trunk 28554) [i686-linux]
> > 	#<Errno::EPIPE: Broken pipe>
> > 	[Hang Here]
[...]
> And in this case here, I call into question the behavior of Ruby and
> the application from two perspectives:
> 
> 1) Unlike all of the other conditions signalled by poll() this is
>    one the application explicitly created and therefore knows about.
>
>    If the application calls close() or shutdown() with the send flag
>    set, IT KNOWS what is going to happen on a write() attempt.
[...]

This example seems to have both server (serv, s2) and client (s1) in the
same process for simplicity.  The server socket (s2) is closed and the
client cannot be expected to know that.  Of course the client ought to
drop the connection after the first EPIPE, but it's reasonable to expect
that this is a sticky condition just as it would be for a pipe.

Here's a similar test case in C:

#include <assert.h>
#include <signal.h>
#include <stdio.h>

#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    struct sockaddr sa;
    struct timeval tv;
    int serv, s1, s2;
    socklen_t len;
    fd_set fds;

    signal(SIGPIPE, SIG_IGN);

    serv = socket(AF_INET, SOCK_STREAM, 0);
    assert(serv >= 0);
    assert(!listen(serv, 1));
    len = sizeof(sa);
    assert(!getsockname(serv, &sa, &len));

    s1 = socket(AF_INET, SOCK_STREAM, 0);
    assert(s1 >= 0);
    assert(!connect(s1, &sa, len));
    len = sizeof(sa);

    s2 = accept(serv, &sa, &len);
    assert(s2 >= 0);
    close(s2);

    for (;;) {
	printf("write: %d\n", write(s1, "a", 1));
	FD_ZERO(&fds);
	FD_SET(s1, &fds);
	tv.tv_sec = 1;
	tv.tv_usec = 0;
	printf("select: %d\n", select(s1 + 1, NULL, &fds, NULL, &tv));
    }
    return 0;
}

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ