All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jean Tourrilhes <jt@bougret.hpl.hp.com>
To: Marcel Holtmann <marcel@holtmann.org>
Cc: Max Krasnyansky <maxk@qualcomm.com>,
	BlueZ Mailing List <bluez-devel@lists.sourceforge.net>
Subject: Re: L2CAP non-blocking socket nasty race conditions
Date: Wed, 4 Feb 2004 19:30:19 -0800	[thread overview]
Message-ID: <20040205033019.GA25518@bougret.hpl.hp.com> (raw)
In-Reply-To: <1075948602.2783.129.camel@pegasus>

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

On Thu, Feb 05, 2004 at 03:36:43AM +0100, Marcel Holtmann wrote:
> Hi Jean,
> 
> > > What I am thinking is that
> > > if our socket is BT_LISTEN, we check for an not empty accept_q and than
> > > iterate through all sockets for BT_CONNECTED. If we found one, we return
> > > POLLIN else nothing.
> > 
> > 	This is a bit yucky, especially that poll is performance
> > critical (for scalability). That's why I was suggesting the socket
> > counter in the parent. Check what's sk_ack_backlog does, it's very
> > close to what we want.
> 
> yes I know, but worse performance only kicks in if it is a listen socket
> and if it has at minimum one child in its queue. A second counter sounds
> not really better to me and I think it will be very hackish.
> 
> Regards
> 
> Marcel

	I implemented the option that you prefered. The patch is
attached.
	I also fixed the "potential" sendmsg race as I understand it
(the one I can't reproduce).

	The good news is that accept no longer returns EAGAIN and my
code no longer tight-loop.
	The problem with the patch is that I get this in my log :
------------------------------------------------------------
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 1
...
...
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 0
J2 - bt_accept_checkqueue - parent ccc11600 backlog 1 num 1
------------------------------------------------------------
	So, in other words I've just moved a tight loop from my code
to the kernel code (or glibc). Which means it seems that we only have
half of the solution (or maybe it's normal poll behavior ?).
	I think at that point we will need to get advice from the
network gurus on how socket notification works.

	Have fun...

	Jean

[-- Attachment #2: bt262_accept_race-1.diff --]
[-- Type: text/plain, Size: 2015 bytes --]

diff -u -p linux/net/bluetooth/af_bluetooth.j2.c linux/net/bluetooth/af_bluetooth.c
--- linux/net/bluetooth/af_bluetooth.j2.c	Wed Feb  4 18:51:55 2004
+++ linux/net/bluetooth/af_bluetooth.c	Wed Feb  4 19:09:15 2004
@@ -200,6 +200,30 @@ struct sock *bt_accept_dequeue(struct so
 	return NULL;
 }
 
+static int bt_accept_checkqueue(struct sock *parent)
+{
+	struct list_head *p, *n;
+	struct sock *sk;
+	int num = 0;
+	
+	BT_DBG("parent %p", parent);
+
+	/* Check the number of connected sockets. This is used in poll
+	 * to know if the socket can really perform an accept.
+	 * Jean II */
+	list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
+		sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
+
+		/* No need to lock, reading/writing ints is atomic and we
+		 * don't need to synchronise. Jean II */
+		if (sk->sk_state == BT_CONNECTED)
+			num++;
+	}
+	printk(KERN_DEBUG "J2 - %s - parent %p backlog %d num %d\n",
+	       __FUNCTION__, parent, parent->sk_ack_backlog, num);
+	return num;
+}
+
 int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 	struct msghdr *msg, size_t len, int flags)
 {
@@ -252,15 +276,23 @@ unsigned int bt_sock_poll(struct file * 
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 
+	/* Check is we can read() (== received packet) or
+	 * if we can accept() (== incomming connection) or
+	 * if the socket died. Jean II */
 	if (!skb_queue_empty(&sk->sk_receive_queue) || 
-			!list_empty(&bt_sk(sk)->accept_q) ||
+			(!list_empty(&bt_sk(sk)->accept_q) &&
+				bt_accept_checkqueue(sk) > 0) ||
 			(sk->sk_shutdown & RCV_SHUTDOWN))
 		mask |= POLLIN | POLLRDNORM;
 
 	if (sk->sk_state == BT_CLOSED)
 		mask |= POLLHUP;
 
-	if (sk->sk_state == BT_CONNECT || sk->sk_state == BT_CONNECT2)
+	/* Socket can't be writeable if it's not yet connected, check
+	 * l2cap_sock_sendmsg() for details. Jean II */
+	if (sk->sk_state == BT_CONNECT ||
+	    sk->sk_state == BT_CONNECT2 ||
+	    sk->sk_state == BT_CONFIG)
 		return mask;
 	
 	if (sock_writeable(sk))

  parent reply	other threads:[~2004-02-05  3:30 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-04  1:58 L2CAP non-blocking socket nasty race conditions Jean Tourrilhes
2004-02-04  7:17 ` [Bluez-devel] " Marcel Holtmann
2004-02-04 17:58   ` Jean Tourrilhes
2004-02-04 19:58     ` [Bluez-devel] " Marcel Holtmann
2004-02-04 21:45       ` Jean Tourrilhes
2004-02-05  1:00         ` [Bluez-devel] " Marcel Holtmann
2004-02-05  1:11           ` Jean Tourrilhes
2004-02-05  1:30             ` [Bluez-devel] " Marcel Holtmann
2004-02-05  1:40               ` Jean Tourrilhes
2004-02-05  2:21                 ` [Bluez-devel] " Marcel Holtmann
2004-02-05  2:26                   ` Jean Tourrilhes
2004-02-05  2:36                     ` [Bluez-devel] " Marcel Holtmann
2004-02-05  2:42                       ` Jean Tourrilhes
2004-02-05  3:30                       ` Jean Tourrilhes [this message]
2004-02-05 13:49                         ` [Bluez-devel] " Marcel Holtmann
2004-02-05 17:19                           ` Jean Tourrilhes
2004-02-05 18:17                             ` [Bluez-devel] " Marcel Holtmann
2004-02-05 23:13                               ` Jean Tourrilhes
2004-02-05 23:37                                 ` [Bluez-devel] " Marcel Holtmann
2004-02-05 23:43                                   ` Jean Tourrilhes
2004-02-04 11:23 ` [Bluez-devel] bluez & qos Mauro Tortonesi
2004-02-04 11:36   ` Marcel Holtmann
2004-02-04 17:46   ` [Bluez-devel] " Jean Tourrilhes
2004-02-05 10:46     ` Mauro Tortonesi
2004-02-05 17:22       ` Jean Tourrilhes

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=20040205033019.GA25518@bougret.hpl.hp.com \
    --to=jt@bougret.hpl.hp.com \
    --cc=bluez-devel@lists.sourceforge.net \
    --cc=jt@hpl.hp.com \
    --cc=marcel@holtmann.org \
    --cc=maxk@qualcomm.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.