From owner-freebsd-net@FreeBSD.ORG Thu Dec 17 15:46:59 2009 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E1FA110656A4 for ; Thu, 17 Dec 2009 15:46:59 +0000 (UTC) (envelope-from to.my.trociny@gmail.com) Received: from mail-bw0-f213.google.com (mail-bw0-f213.google.com [209.85.218.213]) by mx1.freebsd.org (Postfix) with ESMTP id 67FAB8FC5A for ; Thu, 17 Dec 2009 15:46:59 +0000 (UTC) Received: by bwz5 with SMTP id 5so1563485bwz.3 for ; Thu, 17 Dec 2009 07:46:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:to:subject:organization:from :date:message-id:user-agent:mime-version:content-type; bh=+UMGiZma0u5jgZjEqoL5XNQ/E5VmB9LMLBiRZ3yd4Oc=; b=lAS2OhL9qmD5N62SIkX6NC9mw49ljm+EOOKM1SSAORatVO8UBnMFEfPgrJG0uedVGb fUJFhGSS0zB49PM+YAX0mRxyiKxtmqN6euenTOmFqAbHmbf9KV/1Is3vydz6HDiqRZba 1xN2idzo2Au2elQtfWCCCc36JktlR8RJv5Bwg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=to:subject:organization:from:date:message-id:user-agent :mime-version:content-type; b=P7ZVC/5PKGkSVcXNX/hIRXmdd3yM3nWJfq7rZWha5JOfrtPpgBEEvt89MyPEyuSVZl JkSO0Er8w+A+/g+1Uz8I65PAhFqf0qT0AQOrVuY8KUHwOIXEk9fsT164rOZ5x5gceONM EreUk4I897iztP/11s5sUjy+RgzXgqdMi/nuM= Received: by 10.204.10.18 with SMTP id n18mr1432679bkn.152.1261064818426; Thu, 17 Dec 2009 07:46:58 -0800 (PST) Received: from localhost (ms.singlescrowd.net [80.85.90.67]) by mx.google.com with ESMTPS id 14sm647654bwz.5.2009.12.17.07.46.56 (version=TLSv1/SSLv3 cipher=RC4-MD5); Thu, 17 Dec 2009 07:46:57 -0800 (PST) To: FreeBSD-NET Organization: TOA Ukraine From: Mikolaj Golub Date: Thu, 17 Dec 2009 17:46:55 +0200 Message-ID: <86aaxhfvrk.fsf@zhuzha.ua1> User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.3 (berkeley-unix) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Subject: close: Socket is not connected X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Dec 2009 15:47:00 -0000 Hi, We have an application that consists of two processes communicating via unix socket (client connects, sends requests, reads response and close the connection). Sometimes the error 'Socket is not connected' is observed when client closes the socket. We observed this problem on FreeBSD6.X and now have been observing it on 7.1. To model the behaviour of the application I have written a simple test program (see below) based on relevant parts from the application code. Using this test program it requires from an a half of hour to several hours to reproduce the error. It might fail on close() both in the parent (server) and the children (client). $ date; ./unixsocket ; date Thu Dec 17 09:38:35 UTC 2009 unixsocket: parent: close error: 57 Thu Dec 17 14:13:07 UTC 2009 unixsocket: child: connect error 61 $ ./unixsocket unixsocket: child: close error: 57 I can reproduce the error running the test on 8.0 too. Does this indicate some bug in FreeBSD or may be just something is wrong with our code? #include #include #include #include #include #include #include #include #include #include #include #include #include #define UNIXSTR_PATH "/tmp/mytest.socket" #define BUFSIZE 557 #define USLEEP 10000 #define timeout 10 int waitData(int handle, int reading, int writing) { struct timeval tv; int result; fd_set rset; fd_set wset; fd_set eset; FD_ZERO(&rset); FD_SET(handle, &rset); FD_ZERO(&wset); FD_SET(handle, &wset); FD_ZERO(&eset); FD_SET(handle, &eset); tv.tv_sec = timeout; tv.tv_usec = 0; for (;;) { if (reading && !writing) result = select(handle + 1, &rset, 0, &eset, &tv); else if (!reading && writing) result = select(handle + 1, 0, &wset, &eset, &tv); else result = select(handle + 1, &rset, &wset, &eset, &tv); if (result == 0) /* timeout */ return 0; if (result < 0) { if (errno == EINTR) { continue; } errx(1, "select: %d", errno); } if (FD_ISSET(handle, &rset) || FD_ISSET(handle, &wset)) { int err = 0; socklen_t err_size = sizeof(err); if (getsockopt(handle, SOL_SOCKET, SO_ERROR, (char*)&err, &err_size) != 0) { errx(1, "getsockopts: %d", errno); } if (err != 0) { errx(1, "getsockopts: err: %d", err); } } else { errx(1, "select problems"); } return 1; /* OK */ } } void Write(int handle, const char* buf, size_t size) { size_t left = size; while (left > 0) { while (1) { int sent = send(handle, buf, size, 0); if (sent <= 0) { if (errno == EAGAIN) { if (!waitData(handle, 0, 1)) errx(1, "Write: timeout"); continue; } errx(1, "Write: error: %d", errno); } left -= sent; buf += sent; break; } } } void Read(int handle, char* buf, size_t size) { while (size > 0) { int blockSize; if (!waitData(handle, 1, 0)) errx(1, "Read: timeout"); blockSize = recv(handle, buf, size, 0); if (blockSize <= 0) { errx(1, "Read: error: blockSize: %d", blockSize); } buf += blockSize; size -= blockSize; } } int main(int argc, char **argv) { int listenfd, connfd, pid; struct sockaddr_un servaddr; char buf[BUFSIZE]; memset(buf, 'X', sizeof(buf)); pid = fork(); if (-1 == pid) errx(1, "fork(): %d", errno); if (0 != pid) { /* parent */ if ((listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) errx(1, "parent: socket error: %d", errno); unlink(UNIXSTR_PATH); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXSTR_PATH); if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) errx(1, "parent: bind error: %d", errno); if (listen(listenfd, 1024) < 0) errx(1, "parent: listen error: %d", errno); for ( ; ; ) { if ((connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) < 0) errx(1, "parent: accept error: %d", errno); if (fcntl(connfd, F_SETFL, O_NONBLOCK) == -1) errx(1, "parent: fcntl error: %d", errno); Read(connfd, buf, sizeof(buf)); Write(connfd, buf, sizeof(buf)); if (close(connfd) < 0) errx(1, "parent: close error: %d", errno); } } else { /* child */ /* wait some time while parent has created socket */ sleep(1); for ( ; ; ) { if ((connfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) errx(1, "child: socket error: %d", errno); if (fcntl(connfd, F_SETFL, O_NONBLOCK) == -1) errx(1, "child: fcntl error: %d", errno); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXSTR_PATH); if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) errx(1, "child: connect error %d", errno); Write(connfd, buf, sizeof(buf)); Read(connfd, buf, sizeof(buf)); if (close(connfd) != 0) errx(1, "child: close error: %d", errno); usleep(USLEEP); } } return 0; } -- Mikolaj Golub