From owner-freebsd-hackers@FreeBSD.ORG Tue Jan 29 17:46:09 2013 Return-Path: Delivered-To: freebsd-hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id B7D782D9 for ; Tue, 29 Jan 2013 17:46:09 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from duck.symmetricom.us (duck.symmetricom.us [206.168.13.214]) by mx1.freebsd.org (Postfix) with ESMTP id 6BA6BBDF for ; Tue, 29 Jan 2013 17:46:09 +0000 (UTC) Received: from damnhippie.dyndns.org (daffy.symmetricom.us [206.168.13.218]) by duck.symmetricom.us (8.14.6/8.14.6) with ESMTP id r0THk8MH069077 for ; Tue, 29 Jan 2013 10:46:08 -0700 (MST) (envelope-from ian@FreeBSD.org) Received: from [172.22.42.240] (revolution.hippie.lan [172.22.42.240]) by damnhippie.dyndns.org (8.14.3/8.14.3) with ESMTP id r0THk6KE022532; Tue, 29 Jan 2013 10:46:06 -0700 (MST) (envelope-from ian@FreeBSD.org) Subject: Re: Sockets programming question From: Ian Lepore To: Konstantin Belousov In-Reply-To: <20130128160238.GT2522@kib.kiev.ua> References: <1359385907.93359.84.camel@revolution.hippie.lan> <20130128160238.GT2522@kib.kiev.ua> Content-Type: text/plain; charset="us-ascii" Date: Tue, 29 Jan 2013 10:46:05 -0700 Message-ID: <1359481565.93359.160.camel@revolution.hippie.lan> Mime-Version: 1.0 X-Mailer: Evolution 2.32.1 FreeBSD GNOME Team Port Content-Transfer-Encoding: 7bit Cc: freebsd-hackers X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Jan 2013 17:46:09 -0000 On Mon, 2013-01-28 at 18:02 +0200, Konstantin Belousov wrote: > On Mon, Jan 28, 2013 at 08:11:47AM -0700, Ian Lepore wrote: > > I've got a question that isn't exactly freebsd-specific, but > > implemenation-specific behavior may be involved. > > > > I've got a server process that accepts connections from clients on a > > PF_LOCAL stream socket. Multiple clients can be connected at once; a > > list of them is tracked internally. The server occasionally sends data > > to each client. The time between messages to clients can range > > literally from milliseconds to months. Clients never send any data to > > the server, indeed they may shutdown that side of the connection and > > just receive data. > > > > The only way I can find to discover that a client has disappeared is by > > trying to send them a message and getting an error because they've > > closed the socket or died completely. At that point I can reap the > > resources and remove them from the client list. This is problem because > > of the "months between messages" thing. A lot of clients can come and > > go during those months and I've got this ever-growing list of open > > socket descriptors because I never had anything to say the whole time > > they were connected. > > > > By trial and error I've discovered that I can sort of "poll" for their > > presence by writing a zero-length message. If the other end of the > > connection is gone I get the expected error and can reap the client, > > otherwise it appears to quietly write nothing and return zero and have > > no other side effects than polling the status of the server->client side > > of the pipe. > > > > My problem with this "polling" is that I can't find anything in writing > > that sanctions this behavior. Would this amount to relying on a > > non-portable accident of the current implementation? > > > > Also, am I missing something simple and there's a cannonical way to > > handle this? In all the years I've done client/server stuff I've never > > had quite this type of interaction (or lack thereof) between client and > > server before. > > Check for the IN events as well. I would not trust the mere presence > of the IN in the poll result, but consequent read should return EOF > and this is good indicator of the dead client. You can't use EOF on a read() to determine client life when the nature of the client/server relationship is that clients are allowed to shutdown(fd, SHUT_WR) as soon as they connect because they expect to receive but never send any data. On the other hand, Alfred's suggestion of using poll(2) rather than select(2) worked perfectly. Polling with an events mask of zero results in it returning POLLHUP in revents if the client has closed the socket. -- Ian