linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] select for UNIX sockets - 2.4 and 2.5
@ 2003-06-14 15:29 Krzysztof Halasa
  0 siblings, 0 replies; only message in thread
From: Krzysztof Halasa @ 2003-06-14 15:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alan Cox, Andrea Arcangeli

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

Hi,

The attached patches aims to fix select(write) on connect()ed UNIX
datagram sockets. Without this patch, such select() is basically a NOP
i.e. it returns immediately indicating a datagram can be written.

As I don't know this part of the kernel very well I'd appreciate it if
you who know it better check the patch for correctness.

A simple test program is attached as well.

This patch doesn't fix select(write) on unconnect()ed sockets as there
is no obvious way to check for socket state.
-- 
Krzysztof Halasa
Network Administrator

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dgram-sockets-2.4.patch --]
[-- Type: text/x-patch, Size: 1511 bytes --]

--- linux-2.4.orig/net/unix/af_unix.c	2002-11-29 00:53:16.000000000 +0100
+++ linux-2.4/net/unix/af_unix.c	2003-06-14 17:04:26.000000000 +0200
@@ -1707,6 +1707,39 @@
 	return err;
 }
 
+static unsigned int dgram_poll(struct file * file, struct socket *sock,
+			       poll_table *wait)
+{
+        struct sock *sk = sock->sk;
+        unsigned int mask;
+	unix_socket *other;
+
+        poll_wait(file, sk->sleep, wait);
+        mask = 0;
+
+        /* exceptional events? */
+        if (sk->err || !skb_queue_empty(&sk->error_queue))
+                mask |= POLLERR;
+        if (sk->shutdown == SHUTDOWN_MASK)
+                mask |= POLLHUP;
+
+        /* readable? */
+        if (!skb_queue_empty(&sk->receive_queue) ||
+            (sk->shutdown & RCV_SHUTDOWN))
+                mask |= POLLIN | POLLRDNORM;
+
+        /* writable? */
+	other = unix_peer_get(sk);
+	if (sock_writeable(sk) &&
+	    (other == NULL ||
+	     skb_queue_len(&other->receive_queue) <= other->max_ack_backlog))
+                mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+        else
+                set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+	return mask;
+}
+
 static unsigned int unix_poll(struct file * file, struct socket *sock, poll_table *wait)
 {
 	struct sock *sk = sock->sk;
@@ -1836,7 +1869,7 @@
 	socketpair:	unix_socketpair,
 	accept:		sock_no_accept,
 	getname:	unix_getname,
-	poll:		datagram_poll,
+	poll:		dgram_poll,
 	ioctl:		unix_ioctl,
 	listen:		sock_no_listen,
 	shutdown:	unix_shutdown,

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: dgram-sockets-2.5.patch --]
[-- Type: text/x-patch, Size: 1524 bytes --]

--- linux-2.5.orig/net/unix/af_unix.c	2003-05-27 03:00:41.000000000 +0200
+++ linux-2.5/net/unix/af_unix.c	2003-06-14 16:31:59.000000000 +0200
@@ -1784,6 +1784,39 @@
 	return err;
 }
 
+static unsigned int dgram_poll(struct file * file, struct socket *sock,
+			       poll_table *wait)
+{
+        struct sock *sk = sock->sk;
+        unsigned int mask;
+	unix_socket *other;
+
+        poll_wait(file, sk->sleep, wait);
+        mask = 0;
+
+        /* exceptional events? */
+        if (sk->err || !skb_queue_empty(&sk->error_queue))
+                mask |= POLLERR;
+        if (sk->shutdown == SHUTDOWN_MASK)
+                mask |= POLLHUP;
+
+        /* readable? */
+        if (!skb_queue_empty(&sk->receive_queue) ||
+            (sk->shutdown & RCV_SHUTDOWN))
+                mask |= POLLIN | POLLRDNORM;
+
+        /* writable? */
+	other = unix_peer_get(sk);
+	if (sock_writeable(sk) &&
+	    (other == NULL ||
+	     skb_queue_len(&other->receive_queue) <= other->max_ack_backlog))
+                mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+        else
+                set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+	return mask;
+}
+
 static unsigned int unix_poll(struct file * file, struct socket *sock, poll_table *wait)
 {
 	struct sock *sk = sock->sk;
@@ -1913,7 +1946,7 @@
 	.socketpair =	unix_socketpair,
 	.accept =	sock_no_accept,
 	.getname =	unix_getname,
-	.poll =		datagram_poll,
+	.poll =		dgram_poll,
 	.ioctl =	unix_ioctl,
 	.listen =	sock_no_listen,
 	.shutdown =	unix_shutdown,

[-- Attachment #4: sockets.c --]
[-- Type: application/octet-stream, Size: 2027 bytes --]

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

#define DEST_SOCKET "/tmp/test"
#define CONNECT_FIRST 1
#define DEBUG 0

void sender()
{
	int fd;
	struct sockaddr_un addr;
	int addr_len;
	char datagram[1];
	fd_set set;

	fd = socket(PF_UNIX, SOCK_DGRAM, 0);
	if (fd < 0)
		perror("sender's socket() failed");

	addr.sun_family = AF_UNIX;
	strcpy(addr.sun_path, DEST_SOCKET);
	addr_len = sizeof(addr.sun_family) + strlen(addr.sun_path);

	sleep(1);

#if CONNECT_FIRST
	if (connect(fd, (struct sockaddr*)&addr, addr_len) < 0)
		perror("sender's connect failed");
#endif
	while(1) {
		FD_ZERO(&set);
		FD_SET(fd, &set);

		if (select(fd + 1, NULL, &set, NULL, NULL) < 0)
			perror("sender's select() failed");
		if (FD_ISSET(fd, &set)) {
#if DEBUG
			fprintf(stderr, "Sending...");
#endif
#if CONNECT_FIRST
			if (send(fd, &datagram, sizeof(datagram), 0) < 0)
				perror("\nsend() failed");
#else
			if (sendto(fd, &datagram, sizeof(datagram), 0,
				   (struct sockaddr*)&addr, addr_len) < 0)
				perror("\nsendto() failed");
#endif
#if DEBUG
			fprintf(stderr, "\n");
#endif
		}
	}
}


void receiver()
{

	int fd;
	struct sockaddr_un addr;
	int addr_len;
	char datagram[2000];

	fd = socket(PF_UNIX, SOCK_DGRAM, 0);
	if (fd < 0)
		perror("socket failed");

	addr.sun_family = AF_UNIX;
	strcpy(addr.sun_path, DEST_SOCKET);
	addr_len = sizeof(addr.sun_family) + strlen(addr.sun_path);
	if (bind(fd, (struct sockaddr*)&addr, addr_len) < 0)
		perror("receiver's bind() failed");

	while(1) {
		int i, size;
		sleep(10);

		for (i = 0; i < 5; i++) {
			size = recvfrom(fd, &datagram, sizeof(datagram), 0,
					NULL, NULL);
			if (size < 0)
				perror("recv failed");
#if DEBUG
			else
				fprintf(stderr, "recv %i byte(s)\n", size);
#endif
		}
	}
}


int main()
{
	unlink(DEST_SOCKET);

	int result = fork();
	if (result < 0) {
		perror("fork failed");
		exit(1);
	} else if (result == 0)
		receiver();
	else
		sender();

	exit(0);
}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-06-14 15:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-14 15:29 [PATCH] select for UNIX sockets - 2.4 and 2.5 Krzysztof Halasa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).