Skip to contentSkip to conversation

select for UNIX sockets - 2.4 and 2.5

PATCH New Krzysztof Halasa 1 participant 1 message Jun 14, 2003

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 select for UNIX sockets - 2.4 and 2.5

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.

Signature · 2 lines
Krzysztof Halasa
Network Administrator
net/unix/af_unix.c +34 -1
@@ -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,
net/unix/af_unix.c +34 -1
@@ -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,