public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Yasuma Takeda <yasuma@miraclelinux.com>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] removed socket buffer in unix domain socket
Date: Mon, 7 Jan 2002 17:39:44 +0900	[thread overview]
Message-ID: <20020107173944.05623687.yasuma@miraclelinux.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1147 bytes --]


Hi,

I found a problem to unix domain socket.

The unix_gc function removes socket buffers of the socket
which is connectted but not acceptted yet.

After one process executes "Mark phase" of unix_gc function,
another process registers socket buffer by using sendmsg with SCM_RIGHTS.
At the next moment, the socket buffer is removed.

I attached the test program.
When I execute one server and two clients on SMP machine
(kernel 2.4.16 and PentiumIII x 2), I can reporduce this problem.

Following is a patch to avoid this problem.

--- kernel-2.4.16/net/unix/garbage.c.sv       Mon Jan  7 15:46:22 2002
+++ kernel-2.4.16/net/unix/garbage.c  Mon Jan  7 15:51:22 2002
@@ -279,7 +279,7 @@
                                /*
                                 *      Do we have file descriptors ?
                                 */
-                               if(UNIXCB(skb).fp)
+                               if(s->dead && UNIXCB(skb).fp)
                                {
                                        __skb_unlink(skb, skb->list);
                                        __skb_queue_tail(&hitlist,skb);


Regards,

 Yasuma Takeda



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: client.c --]
[-- Type: text/x-csrc; name="client.c", Size: 2449 bytes --]

#include <stdio.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>

main(int argc,char ** argv)
{

	struct sockaddr_un sockaddr;
	char line[128];
	char reply[128];
	int socket_errno;
	int i, err, n;
	int s;
	int ret;
	int	fd[2];
	struct 	cmsghdr *cmsg;
	int 	*fdptr;
	char 	cmsgbuf[CMSG_SPACE(sizeof (int))];
	struct iovec vec;
	struct msghdr msghdr;

	if ( socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1 ) {
		fprintf(stderr, "socketpait error\n");
	}
	close(fd[1]);

	n = 0;
	while (1) {
		if ((s=socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
			socket_errno = errno;
			fprintf(stderr,"can't create socket [%d]\n",socket_errno);
			exit(-1);
		}

		memset(&sockaddr, '\0', sizeof(sockaddr));
		sockaddr.sun_family      = AF_UNIX;
		strcpy(sockaddr.sun_path, "/tmp/unix_d_test");
		
		if (connect(s,(struct sockaddr *)&sockaddr,sizeof(sockaddr)) == -1) {
			socket_errno = errno;
			fprintf(stderr,"connect error [%d]\n",errno);
			exit(-1);
		}
		
		for(i = 0 ; i < 128 ; i++) {
			line[i] = 0;
		}
		sprintf(line, "[%d]:client pid is %d", n, getpid());
		
		vec.iov_base = line;
		vec.iov_len  = 128;
		
		msghdr.msg_name       = NULL;
		msghdr.msg_namelen    = 0;
		msghdr.msg_iov        = &vec;
		msghdr.msg_iovlen     = 1;
		msghdr.msg_flags = 0;
		
		msghdr.msg_control = cmsgbuf;
		msghdr.msg_controllen = sizeof cmsgbuf;
		cmsg = CMSG_FIRSTHDR(&msghdr);
		cmsg->cmsg_len   = CMSG_LEN(sizeof(int) * 1);
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type  = SCM_RIGHTS;
		fdptr = (int *)CMSG_DATA(cmsg);
		memcpy(fdptr, fd, sizeof(int) * 1);
		msghdr.msg_controllen = cmsg->cmsg_len;
		
		if ((ret = sendmsg(s, &msghdr, 0 )) < 128) {
			fprintf(stderr, "sendmsg error %d\n", errno);
			exit(-1);
		}
		fprintf(stderr, "[%d]:sendmsg() %d byte OK. fd:%d\n", n, ret, fd[0]);
		
		vec.iov_base = reply;
		vec.iov_len  = 128;
		
		msghdr.msg_name       = NULL;
		msghdr.msg_namelen    = 0;
		msghdr.msg_iov        = &vec;
		msghdr.msg_iovlen     = 1;
		msghdr.msg_flags = 0;
		msghdr.msg_controllen = 0;
		msghdr.msg_control    = NULL;
		
		if ((ret = recvmsg(s, &msghdr, 0)) < 128) {
			fprintf(stderr, "recvmsg() error %d\n", errno);
			exit(-1);
		}
		fprintf(stderr, "recvmgs() %d byte OK.\n", ret);

		close(s);
		n++;
	}
	
	fprintf(stderr,"GOOD BY \n");
	exit (0);
}





[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: server.c --]
[-- Type: text/x-csrc; name="server.c", Size: 3215 bytes --]

#include <stdio.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

main(int argc,char ** argv)
{
	int s;
	struct sockaddr_un sockaddr;
	char line[128];
	char reply[128];
	int socket_errno;
	int i, err;
	int flags;
	fd_set read_set, read_cur;
	int max_fd;
	int ret;
	struct  iovec vec;
	struct  msghdr msghdr;
	int	client_fd;
	struct  cmsghdr *cmsg;
	int	*pass_fd_ptr;
	char	cmsgbuf[CMSG_SPACE(sizeof (int))];
	
	if ((s=socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		socket_errno = errno;
		fprintf(stdout,"can't create socket [%d]\n",socket_errno);
		exit(-1);
	}
	
	unlink("/tmp/unix_d_test");
	memset(&sockaddr, '\0', sizeof(sockaddr));
	sockaddr.sun_family      = AF_UNIX;
	strcpy(sockaddr.sun_path, "/tmp/unix_d_test");
	
	if (bind(s,(struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) {
		socket_errno = errno;
		fprintf(stdout,"can't bind socket [%d]\n",errno);
		exit(-1);
	}
	
	if (listen(s, 10) < 0) {
		fprintf(stdout, "listen() error %d\n", socket_errno);
		exit(-1);
	}

	FD_ZERO(&read_set);
	FD_SET(s, &read_set);
	max_fd = s;
	client_fd = -1;

	for(;;) {
		for(i = 0 ; i < 128 ; i++) {
			line[i] = 0;
		}
		
		read_cur = read_set;
		ret = select(max_fd+1, &read_cur, NULL, NULL, NULL);
		if (ret == -1) {
			fprintf(stdout, "select() error %d\n", errno);
			continue;
		}
		for (i = 0; i <= max_fd; i++) {
			if (FD_ISSET(i, &read_cur)) {
				if (i == s) {
					struct sockaddr_un    address;
					int	len;

					if (client_fd != -1) {
						close(client_fd);
					}

					len = sizeof(struct sockaddr_un);
					client_fd = accept(s, (struct sockaddr *)&address, &len);
					if (client_fd == -1) {
						fprintf(stdout, "accept() error %d\n", errno);
						exit(-1);
					}
					if ( client_fd > max_fd ) max_fd = client_fd;
				} else if (i == client_fd) {
					fprintf(stdout, "read from client_fd\n");
				}
				
				msghdr.msg_name    = NULL;
				msghdr.msg_namelen = 0;
				msghdr.msg_iov     = &vec;
				msghdr.msg_iovlen  = 1;
				msghdr.msg_control    = cmsgbuf;
				msghdr.msg_controllen = sizeof(cmsgbuf);
				vec.iov_base  = line;
				vec.iov_len   = 128;
				if ((ret = recvmsg(client_fd, &msghdr, 0)) < 128) {
					fprintf(stdout, "recvmsg() error %d\n", errno);
					exit(-1);
				}
				for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
					if (cmsg->cmsg_level == SOL_SOCKET) {
						pass_fd_ptr = (int *)CMSG_DATA(cmsg);
						break;
					}
				}
				fprintf(stdout, "recvmsg() is done.\n");
				close(*pass_fd_ptr);

				msghdr.msg_name    = NULL;
				msghdr.msg_namelen = 0;
				msghdr.msg_iov     = &vec;
				msghdr.msg_iovlen  = 1;
				msghdr.msg_controllen = 0;
				msghdr.msg_control    = NULL;
				vec.iov_base  = reply;
				vec.iov_len   = 128;
				if ((ret = sendmsg(client_fd, &msghdr, 0 )) < 128) {
					fprintf(stdout, "sendmsg error %d\n", errno);
					exit(-1);
				}
				fprintf(stdout, "sendmsg() %d byte OK. \n", ret);
				
				FD_ZERO(&read_set);
				FD_SET(s, &read_set);
				break;
			}
		}
		
	}
	fprintf(stdout,"GOOD BY \n");
	exit (0);
}

             reply	other threads:[~2002-01-07  8:40 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-01-07  8:39 Yasuma Takeda [this message]
2002-01-07  9:11 ` [PATCH] removed socket buffer in unix domain socket Alexander Viro
2002-01-07 13:53 ` Alan Cox
2002-01-09 19:49   ` kuznet
2002-01-11 13:23   ` Go Taniguchi
2002-01-11 13:45     ` David S. Miller
2002-01-11 14:03       ` [sd:04032] " Go Taniguchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20020107173944.05623687.yasuma@miraclelinux.com \
    --to=yasuma@miraclelinux.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox