diff options
-rw-r--r-- | kernel/ptrace.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index b0f8da80d7d4..921c22ad16e4 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -155,8 +155,26 @@ int ptrace_attach(struct task_struct *task) | |||
155 | if (task->tgid == current->tgid) | 155 | if (task->tgid == current->tgid) |
156 | goto out; | 156 | goto out; |
157 | 157 | ||
158 | write_lock_irq(&tasklist_lock); | 158 | repeat: |
159 | /* | ||
160 | * Nasty, nasty. | ||
161 | * | ||
162 | * We want to hold both the task-lock and the | ||
163 | * tasklist_lock for writing at the same time. | ||
164 | * But that's against the rules (tasklist_lock | ||
165 | * is taken for reading by interrupts on other | ||
166 | * cpu's that may have task_lock). | ||
167 | */ | ||
159 | task_lock(task); | 168 | task_lock(task); |
169 | local_irq_disable(); | ||
170 | if (!write_trylock(&tasklist_lock)) { | ||
171 | local_irq_enable(); | ||
172 | task_unlock(task); | ||
173 | do { | ||
174 | cpu_relax(); | ||
175 | } while (!write_can_lock(&tasklist_lock)); | ||
176 | goto repeat; | ||
177 | } | ||
160 | 178 | ||
161 | /* the same process cannot be attached many times */ | 179 | /* the same process cannot be attached many times */ |
162 | if (task->ptrace & PT_PTRACED) | 180 | if (task->ptrace & PT_PTRACED) |