diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2011-07-24 00:10:52 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-08-11 18:50:26 -0400 |
commit | f9a3c20aa07462108fc6fd759dea956053f020bb (patch) | |
tree | 3bbb3b9ff3de29fe7b3a69f36ac386e2871b5fd6 /net | |
parent | 9be4e3fbf2d3603e7a7010ede0697166738a788b (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.c | 28 |
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) |