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);
}
next 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