Re: [PATCH] close.2: Mention a need of shutdown before closing socket

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 7 Oct 2011, Michael Kerrisk wrote:

> Hi Lukas
> 
> On Fri, Oct 7, 2011 at 9:09 AM, Lukas Czerner <lczerner@xxxxxxxxxx> wrote:
> > On Fri, 7 Oct 2011, Michael Kerrisk wrote:
> >
> >> Lukas,
> >>
> >> On Mon, Aug 29, 2011 at 2:26 PM, Lukas Czerner <lczerner@xxxxxxxxxx> wrote:
> >> > When dealing with sockets, we have to be sure that there is no recv
> >> > still blocking on it on another thread, otherwise it might block forever,
> >> > since no more messages will be send via the socket. We should advice to
> >> > use shutdown before closing socket.
> >>
> >> I'm looking into this now. The picture may be more complex than this.
> >> Tell me, so you have a Solaris system available for testing?
> >>
> >> Thanks,
> >
> > Hi Michael,
> >
> > Thanks for looking into this. Unfortunately I do not have any Solaris system
> > for testing, that was a customer report. His complaint was mainly not because
> > the behaviour on Linux differs, but because this was not documented anywhere.
> 
> Okay. I will see if I can find a test system somewhere. (The system I
> used to use seems to have gone away.)
> 
> Just FYI: I confirmed what you are seeing, but the issue seems more
> general: basically, closing a file descriptor in one thread while
> reading in another thread does not cause the read operation to
> terminate (it will still read data if/when it becomes available).
> 
> By the way, I'm wondering about creating a small repo of test
> programs. I might like to add a modified version of your test program
> to that repo. Can you put that code under a Free License and supply a
> copyright?
> 
> Thanks,
> 
> Michael

Hi Michael,

no problem, here is the program, feel free to update it as you like.
Thanks for looking into this.

-Lukas

---

/**
 * Copyright 2011 (C) Red Hat, Inc., Lukas Czerner <lczerner@xxxxxxxxxx>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <unistd.h>
#include <pthread.h>

#define BUFSIZE 1024

void *close_socket(void *arg) {
	int sockfd = *(int *)arg;

	sleep(3);
	printf("Thread: closing socket %d\n", sockfd);
//	shutdown(sockfd, SHUT_RDWR);
	close(sockfd);
}

int client(void) {
	int sockfd;
	int len;
	struct sockaddr_un address;
	int ret;
	char *buffer=malloc(BUFSIZE);
	pthread_t thread;

	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

	address.sun_family = AF_UNIX;
	strcpy(address.sun_path, "server_socket");
	len = sizeof(address);

	ret = connect(sockfd, (struct sockaddr *)&address, len);
	if (ret == -1) {
		perror("connect");
		return 1;
	}
	printf("client connected\n");

	ret = pthread_create(&thread, NULL, close_socket, (void *)&sockfd);
	if (ret != 0) {
		perror("Creating thread failed");
		return 1;
	}

	while (1) {
		ret = recv(sockfd,buffer,BUFSIZE,0);
		if (ret < 0) {
			perror("recv");
			return 1;
		}
		printf("Data received: %s\n", buffer);
		sleep(1);
	}

	close(sockfd);
	return 0;
}

int server(void) {
	char *message="This is the message I am sending to you";
	struct sockaddr_un server_addr, client_addr;
	int server_sockfd, client_sockfd;
	int server_len, client_len;
	int ret;

	unlink("server_socket");
	server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

	server_addr.sun_family = AF_UNIX;
	strcpy(server_addr.sun_path, "server_socket");
	server_len = sizeof(server_addr);
	bind(server_sockfd, (struct sockaddr *)&server_addr, server_len);

	listen(server_sockfd, 5);

	client_len = sizeof(client_addr);
	client_sockfd = accept(server_sockfd,
		(struct sockaddr *)&client_addr, &client_len);

	printf("Server: sending data...\n");
	ret = send(client_sockfd ,message,strlen(message),0);
	if (ret < 0) {
		perror("send");
		return 1;
	}

	/* simulate running server by not closing the client_socket socket */
	return 0;
}

int main() {
	pid_t pid;
	int n;
	
	pid = fork();
	if (pid < 0) {
		perror("fork failed");
		exit(1);
	}
	if (pid > 0) {
		printf(" - starting server\n");
		server();
		printf(" - exiting server\n");
		wait();
	} else {
		sleep(1);
		printf(" - starting client\n");
		client();
		printf(" - exiting client\n");
	}
}
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux