From owner-freebsd-stable@FreeBSD.ORG Mon May 17 16:35:00 2010 Return-Path: Delivered-To: freebsd-stable@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D0919106564A; Mon, 17 May 2010 16:35:00 +0000 (UTC) (envelope-from ysarumaru@gmail.com) Received: from mail-vw0-f54.google.com (mail-vw0-f54.google.com [209.85.212.54]) by mx1.freebsd.org (Postfix) with ESMTP id 73EF58FC0C; Mon, 17 May 2010 16:35:00 +0000 (UTC) Received: by vws17 with SMTP id 17so2006596vws.13 for ; Mon, 17 May 2010 09:34:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:date:message-id :subject:from:to:content-type; bh=JJX6Y4SYMORxExvVvdTYWNnqEgrXVgGnNc13SoQwY8c=; b=MezZMntbaBrmNEYrNZXEzlba6NURjbumys+vrVfVGWKsVPqkvzGZlGNv0YcM09/G08 sLfF9YM5sweezJ7Inj8STAWjB8bwMHgQZxfNNPMUi+T9FdQgs7MrLl6FGMlLjXWvcnad 1lRAFMageW+vfuTkbcOOCtz2EaaBM27f/mF1g= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=Be386rrBDKKPCEuJ1KSU6oZHyTOA16VchAWaD+ZTY+/QLgSs/dPajNxci82um6izQJ wovt3GoFbax69tEILTFnL3QymCe+nplkVwqTc3sHV43mvTjoXbcVT/OhmPD2rcZvkgO1 R5omlAXX+9hXl0QUlsAsQI9Axd1G6GeS02lDg= MIME-Version: 1.0 Received: by 10.220.63.10 with SMTP id z10mr2709937vch.70.1274112530645; Mon, 17 May 2010 09:08:50 -0700 (PDT) Received: by 10.220.92.129 with HTTP; Mon, 17 May 2010 09:08:50 -0700 (PDT) Date: Tue, 18 May 2010 01:08:50 +0900 Message-ID: From: Yoshihiko Sarumaru To: freebsd-net@FreeBSD.org, freebsd-stable@FreeBSD.org Content-Type: text/plain; charset=ISO-8859-1 Cc: Subject: odd behavior on select() after shutdown() X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 May 2010 16:35:01 -0000 Hi all, Select(2) has three arguments to get socket status for read, write and except. After upgrading to 8.0-RELEASE, select() after shutdown(SHUT_WR) returns with the status exceptfds is set. It means out-of-bound data can be read from the socket, but recv() with OOB flag returns ECONNRESET, and no packets with urgent flag was observed by tcpdump. It seems strange for me, but is it an intentional change on 8.x ? This behavior breaks net/stone on 8.0-RELEASE. http://www.freebsd.org/cgi/query-pr.cgi?pr=ports/141103 The continuous recv() error on PR might lead by incorrectly setted exceptfds on every recv() and it should be fixed, but it doesn't matter if above behavior of select() doesn't occur. You can reproduce this by following example: #include #include #include #include #include #include int main() { int ret; int s; s = socket(PF_INET, SOCK_STREAM, 0); struct sockaddr_in sa; sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = htons(22); ret = connect(s, (struct sockaddr*)&sa, sizeof(sa)); if (ret) perror("connect"); /* get OpenSSH greetings */ char buf[BUFSIZ]; memset(buf, 0, sizeof(buf) / sizeof(buf[0])); ret = recv(s, buf, sizeof(buf), 0); if (ret < 0) perror("recv"); printf("recv: %s\n", buf); /* send something incorrect */ printf("send: \\r\\n\n"); ret = send(s, "\r\n", 2, 0); if (ret < 0) perror("send"); /* receive "Protocol mismatch" */ memset(buf, 0, sizeof(buf) / sizeof(buf[0])); ret = recv(s, buf, sizeof(buf), 0); if (ret < 0) perror("recv"); printf("recv: %s\n", buf); /* shutdown */ ret = shutdown(s, SHUT_WR); /* SHUT_RD doesn't make problem. */ if (ret) perror("shutdown"); /* select */ fd_set readfds, exceptfds; FD_ZERO(&readfds); FD_ZERO(&exceptfds); FD_SET(s, &readfds); FD_SET(s, &exceptfds); ret = select(s+1, &readfds, NULL, &exceptfds, NULL); if (ret < 1) perror("select"); printf("select: read:%d except:%d\n", FD_ISSET(s, &readfds), FD_ISSET(s, &exceptfds)); if (FD_ISSET(s, &exceptfds)) { printf("read OOB data\n"); memset(buf, 0, sizeof(buf) / sizeof(buf[0])); ret = recv(s, buf, sizeof(buf), MSG_OOB); if (ret < 0) perror("recv"); printf("recv(OOB): %s\n", buf); } FD_ZERO(&readfds); FD_SET(s, &readfds); ret = select(s+1, &readfds, NULL, NULL, NULL); if (ret < 1) perror("select"); printf("select: read:%d\n", FD_ISSET(s, &readfds)); memset(buf, 0, sizeof(buf) / sizeof(buf[0])); ret = recv(s, buf, sizeof(buf), 0); if (ret < 0) perror("recv"); printf("recv: %s\n", buf); close(s); } Thanks in advance - Yoshihiko