aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2011-08-05 10:44:21 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-08-11 18:50:27 -0400
commit7176522cdca1f0b78a1434b41761f0334511822a (patch)
tree58ec3c3fc712536e898bd2d7780361e8a492f22a /net
parent751c10a56802513a6b057c8cf1552cecc1c9afde (diff)
Bluetooth: cmtp: Fix deadlock in session deletion
Commit fada4ac339 introduced the usage of kthread API. kthread_stop is a blocking function which returns only when the thread exits. In this case, the thread can't exit because it's waiting for the write lock, which is being held by cmtp_del_connection() which is waiting for the thread to exit -- deadlock. Revert cmtp_reset_ctr to its original behavior: non-blocking signalling for the session to terminate. 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/cmtp/capi.c3
-rw-r--r--net/bluetooth/cmtp/cmtp.h1
-rw-r--r--net/bluetooth/cmtp/core.c5
3 files changed, 6 insertions, 3 deletions
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 040f67b12978..50f0d135eb8f 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -386,7 +386,8 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl)
386 386
387 capi_ctr_down(ctrl); 387 capi_ctr_down(ctrl);
388 388
389 kthread_stop(session->task); 389 atomic_inc(&session->terminate);
390 wake_up_process(session->task);
390} 391}
391 392
392static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) 393static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h
index db43b54ac9af..c32638dddbf9 100644
--- a/net/bluetooth/cmtp/cmtp.h
+++ b/net/bluetooth/cmtp/cmtp.h
@@ -81,6 +81,7 @@ struct cmtp_session {
81 81
82 char name[BTNAMSIZ]; 82 char name[BTNAMSIZ];
83 83
84 atomic_t terminate;
84 struct task_struct *task; 85 struct task_struct *task;
85 86
86 wait_queue_head_t wait; 87 wait_queue_head_t wait;
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 2eb854ab10f6..42cb2f4c0db1 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -295,7 +295,7 @@ static int cmtp_session(void *arg)
295 while (1) { 295 while (1) {
296 set_current_state(TASK_INTERRUPTIBLE); 296 set_current_state(TASK_INTERRUPTIBLE);
297 297
298 if (kthread_should_stop()) 298 if (atomic_read(&session->terminate))
299 break; 299 break;
300 if (sk->sk_state != BT_CONNECTED) 300 if (sk->sk_state != BT_CONNECTED)
301 break; 301 break;
@@ -416,7 +416,8 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)
416 skb_queue_purge(&session->transmit); 416 skb_queue_purge(&session->transmit);
417 417
418 /* Stop session thread */ 418 /* Stop session thread */
419 kthread_stop(session->task); 419 atomic_inc(&session->terminate);
420 wake_up_process(session->task);
420 } else 421 } else
421 err = -ENOENT; 422 err = -ENOENT;
422 423