diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/signal.c | 50 | 
1 files changed, 44 insertions, 6 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 12ffea7c201d..6c0958e52ea7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c  | |||
| @@ -231,6 +231,40 @@ void flush_signals(struct task_struct *t) | |||
| 231 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 231 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 
| 232 | } | 232 | } | 
| 233 | 233 | ||
| 234 | static void __flush_itimer_signals(struct sigpending *pending) | ||
| 235 | { | ||
| 236 | sigset_t signal, retain; | ||
| 237 | struct sigqueue *q, *n; | ||
| 238 | |||
| 239 | signal = pending->signal; | ||
| 240 | sigemptyset(&retain); | ||
| 241 | |||
| 242 | list_for_each_entry_safe(q, n, &pending->list, list) { | ||
| 243 | int sig = q->info.si_signo; | ||
| 244 | |||
| 245 | if (likely(q->info.si_code != SI_TIMER)) { | ||
| 246 | sigaddset(&retain, sig); | ||
| 247 | } else { | ||
| 248 | sigdelset(&signal, sig); | ||
| 249 | list_del_init(&q->list); | ||
| 250 | __sigqueue_free(q); | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | sigorsets(&pending->signal, &signal, &retain); | ||
| 255 | } | ||
| 256 | |||
| 257 | void flush_itimer_signals(void) | ||
| 258 | { | ||
| 259 | struct task_struct *tsk = current; | ||
| 260 | unsigned long flags; | ||
| 261 | |||
| 262 | spin_lock_irqsave(&tsk->sighand->siglock, flags); | ||
| 263 | __flush_itimer_signals(&tsk->pending); | ||
| 264 | __flush_itimer_signals(&tsk->signal->shared_pending); | ||
| 265 | spin_unlock_irqrestore(&tsk->sighand->siglock, flags); | ||
| 266 | } | ||
| 267 | |||
| 234 | void ignore_signals(struct task_struct *t) | 268 | void ignore_signals(struct task_struct *t) | 
| 235 | { | 269 | { | 
| 236 | int i; | 270 | int i; | 
| @@ -1240,18 +1274,22 @@ void sigqueue_free(struct sigqueue *q) | |||
| 1240 | 1274 | ||
| 1241 | BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); | 1275 | BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); | 
| 1242 | /* | 1276 | /* | 
| 1243 | * If the signal is still pending remove it from the | 1277 | * We must hold ->siglock while testing q->list | 
| 1244 | * pending queue. We must hold ->siglock while testing | 1278 | * to serialize with collect_signal() or with | 
| 1245 | * q->list to serialize with collect_signal() or with | ||
| 1246 | * __exit_signal()->flush_sigqueue(). | 1279 | * __exit_signal()->flush_sigqueue(). | 
| 1247 | */ | 1280 | */ | 
| 1248 | spin_lock_irqsave(lock, flags); | 1281 | spin_lock_irqsave(lock, flags); | 
| 1282 | q->flags &= ~SIGQUEUE_PREALLOC; | ||
| 1283 | /* | ||
| 1284 | * If it is queued it will be freed when dequeued, | ||
| 1285 | * like the "regular" sigqueue. | ||
| 1286 | */ | ||
| 1249 | if (!list_empty(&q->list)) | 1287 | if (!list_empty(&q->list)) | 
| 1250 | list_del_init(&q->list); | 1288 | q = NULL; | 
| 1251 | spin_unlock_irqrestore(lock, flags); | 1289 | spin_unlock_irqrestore(lock, flags); | 
| 1252 | 1290 | ||
| 1253 | q->flags &= ~SIGQUEUE_PREALLOC; | 1291 | if (q) | 
| 1254 | __sigqueue_free(q); | 1292 | __sigqueue_free(q); | 
| 1255 | } | 1293 | } | 
| 1256 | 1294 | ||
| 1257 | int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) | 1295 | int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) | 
