.. | .. |
---|
190 | 190 | spin_lock_irq(&task->sighand->siglock); |
---|
191 | 191 | if (task_is_traced(task) && !looks_like_a_spurious_pid(task) && |
---|
192 | 192 | !__fatal_signal_pending(task)) { |
---|
193 | | - task->state = __TASK_TRACED; |
---|
| 193 | + unsigned long flags; |
---|
| 194 | + |
---|
| 195 | + raw_spin_lock_irqsave(&task->pi_lock, flags); |
---|
| 196 | + if (task->state & __TASK_TRACED) |
---|
| 197 | + task->state = __TASK_TRACED; |
---|
| 198 | + else |
---|
| 199 | + task->saved_state = __TASK_TRACED; |
---|
| 200 | + raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
---|
194 | 201 | ret = true; |
---|
195 | 202 | } |
---|
196 | 203 | spin_unlock_irq(&task->sighand->siglock); |
---|
.. | .. |
---|
200 | 207 | |
---|
201 | 208 | static void ptrace_unfreeze_traced(struct task_struct *task) |
---|
202 | 209 | { |
---|
203 | | - if (task->state != __TASK_TRACED) |
---|
204 | | - return; |
---|
| 210 | + unsigned long flags; |
---|
| 211 | + bool frozen = true; |
---|
205 | 212 | |
---|
206 | 213 | WARN_ON(!task->ptrace || task->parent != current); |
---|
207 | 214 | |
---|
.. | .. |
---|
210 | 217 | * Recheck state under the lock to close this race. |
---|
211 | 218 | */ |
---|
212 | 219 | spin_lock_irq(&task->sighand->siglock); |
---|
213 | | - if (task->state == __TASK_TRACED) { |
---|
214 | | - if (__fatal_signal_pending(task)) |
---|
215 | | - wake_up_state(task, __TASK_TRACED); |
---|
216 | | - else |
---|
217 | | - task->state = TASK_TRACED; |
---|
218 | | - } |
---|
| 220 | + |
---|
| 221 | + raw_spin_lock_irqsave(&task->pi_lock, flags); |
---|
| 222 | + if (task->state == __TASK_TRACED) |
---|
| 223 | + task->state = TASK_TRACED; |
---|
| 224 | + else if (task->saved_state == __TASK_TRACED) |
---|
| 225 | + task->saved_state = TASK_TRACED; |
---|
| 226 | + else |
---|
| 227 | + frozen = false; |
---|
| 228 | + raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
---|
| 229 | + |
---|
| 230 | + if (frozen && __fatal_signal_pending(task)) |
---|
| 231 | + wake_up_state(task, __TASK_TRACED); |
---|
| 232 | + |
---|
219 | 233 | spin_unlock_irq(&task->sighand->siglock); |
---|
220 | 234 | } |
---|
221 | 235 | |
---|