[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <OF9EFE848A.BEC7D34A-ON48257B4F.00105687-48257B4F.0010C79B@zte.com.cn>
Date: Tue, 16 Apr 2013 11:02:46 +0800
From: zhang.yi20@....com.cn
To: linux-kernel@...r.kernel.org
Cc: Peter Zijlstra <peterz@...radead.org>,
Darren Hart <dvhart@...ux.intel.com>,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...nel.org>
Subject: [PATCH] futex: bugfix for robust futex deadlock when waking only one thread
in handle_futex_death
From: Zhang Yi <zhang.yi20@....com.cn>
Hello,
The function handle_futex_death just wakes one thread, which may be not
enough when the owner process is dead. Think about this scene:
1. A robust futex is shared for two processes, each process has multi
threads try to get the lock.
2. One of the threads gets the lock, and the others are waiting and sorted
in order of priority.
3. The process to which the lock owner thread belongs is dying,and
handle_futex_death is called to wake the first waiter
4. When the first waiter belongs to the same process,it has no chance to
return to the userspace to get the lock and will not call
handle_futex_death any
more,and then the rest threads of the other process will never be waked,
and
will block forever.
This patch wakes all the waiters when lock owner is in group-exit, letting
all the waiters return to userspace and try to get the lock again.
Signed-off-by: Zhang Yi <zhang.yi20@....com.cn>
Tested-by: Ma Chenggong <ma.chenggong@....com.cn>
Reviewed-by: Liu Dong <liu.dong3@....com.cn>
Reviewed-by: Cui Yunfeng <cui.yunfeng@....com.cn>
Reviewed-by: Lu Zhongjun <lu.zhongjun@....com.cn>
Reviewed-by: Jiang Biao <jiang.biao2@....com.cn>
--- orig/linux-3.9-rc7/kernel/futex.c 2013-04-15 00:45:16.000000000
+0000
+++ new/linux-3.9-rc7/kernel/futex.c 2013-04-16 10:17:46.264597000
+0000
@@ -2545,8 +2545,11 @@ retry:
* Wake robust non-PI futexes here. The wakeup of
* PI futexes happens in exit_pi_state():
*/
- if (!pi && (uval & FUTEX_WAITERS))
- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
+ if (!pi && (uval & FUTEX_WAITERS)) {
+ int nr = signal_group_exit(current->signal)
+ ? INT_MAX : 1;
+ futex_wake(uaddr, 1, nr, FUTEX_BITSET_MATCH_ANY);
+ }
}
return 0;
}
Powered by blists - more mailing lists