aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2011-07-24 00:10:52 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-08-11 18:50:26 -0400
commitf9a3c20aa07462108fc6fd759dea956053f020bb (patch)
tree3bbb3b9ff3de29fe7b3a69f36ac386e2871b5fd6 /net
parent9be4e3fbf2d3603e7a7010ede0697166738a788b (diff)
Bluetooth: l2cap: Fix lost wakeups waiting to accept socket
Fix race conditions which can cause lost wakeups (or misssed signals) while waiting to accept an l2cap socket connection. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_sock.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 5c36b3e8739c..7d713b1c4cbd 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -235,30 +235,26 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
235 235
236 lock_sock_nested(sk, SINGLE_DEPTH_NESTING); 236 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
237 237
238 if (sk->sk_state != BT_LISTEN) {
239 err = -EBADFD;
240 goto done;
241 }
242
243 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); 238 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
244 239
245 BT_DBG("sk %p timeo %ld", sk, timeo); 240 BT_DBG("sk %p timeo %ld", sk, timeo);
246 241
247 /* Wait for an incoming connection. (wake-one). */ 242 /* Wait for an incoming connection. (wake-one). */
248 add_wait_queue_exclusive(sk_sleep(sk), &wait); 243 add_wait_queue_exclusive(sk_sleep(sk), &wait);
249 while (!(nsk = bt_accept_dequeue(sk, newsock))) { 244 while (1) {
250 set_current_state(TASK_INTERRUPTIBLE); 245 set_current_state(TASK_INTERRUPTIBLE);
251 if (!timeo) { 246
252 err = -EAGAIN; 247 if (sk->sk_state != BT_LISTEN) {
248 err = -EBADFD;
253 break; 249 break;
254 } 250 }
255 251
256 release_sock(sk); 252 nsk = bt_accept_dequeue(sk, newsock);
257 timeo = schedule_timeout(timeo); 253 if (nsk)
258 lock_sock_nested(sk, SINGLE_DEPTH_NESTING); 254 break;
259 255
260 if (sk->sk_state != BT_LISTEN) { 256 if (!timeo) {
261 err = -EBADFD; 257 err = -EAGAIN;
262 break; 258 break;
263 } 259 }
264 260
@@ -266,8 +262,12 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
266 err = sock_intr_errno(timeo); 262 err = sock_intr_errno(timeo);
267 break; 263 break;
268 } 264 }
265
266 release_sock(sk);
267 timeo = schedule_timeout(timeo);
268 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
269 } 269 }
270 set_current_state(TASK_RUNNING); 270 __set_current_state(TASK_RUNNING);
271 remove_wait_queue(sk_sleep(sk), &wait); 271 remove_wait_queue(sk_sleep(sk), &wait);
272 272
273 if (err) 273 if (err)