diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 64 |
1 files changed, 33 insertions, 31 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index bc71fdfcd8a7..f132349c0325 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -185,21 +185,19 @@ repeat: | |||
185 | * This checks not only the pgrp, but falls back on the pid if no | 185 | * This checks not only the pgrp, but falls back on the pid if no |
186 | * satisfactory pgrp is found. I dunno - gdb doesn't work correctly | 186 | * satisfactory pgrp is found. I dunno - gdb doesn't work correctly |
187 | * without this... | 187 | * without this... |
188 | * | ||
189 | * The caller must hold rcu lock or the tasklist lock. | ||
188 | */ | 190 | */ |
189 | int session_of_pgrp(int pgrp) | 191 | struct pid *session_of_pgrp(struct pid *pgrp) |
190 | { | 192 | { |
191 | struct task_struct *p; | 193 | struct task_struct *p; |
192 | int sid = 0; | 194 | struct pid *sid = NULL; |
193 | |||
194 | read_lock(&tasklist_lock); | ||
195 | 195 | ||
196 | p = find_task_by_pid_type(PIDTYPE_PGID, pgrp); | 196 | p = pid_task(pgrp, PIDTYPE_PGID); |
197 | if (p == NULL) | 197 | if (p == NULL) |
198 | p = find_task_by_pid(pgrp); | 198 | p = pid_task(pgrp, PIDTYPE_PID); |
199 | if (p != NULL) | 199 | if (p != NULL) |
200 | sid = process_session(p); | 200 | sid = task_session(p); |
201 | |||
202 | read_unlock(&tasklist_lock); | ||
203 | 201 | ||
204 | return sid; | 202 | return sid; |
205 | } | 203 | } |
@@ -212,47 +210,47 @@ int session_of_pgrp(int pgrp) | |||
212 | * | 210 | * |
213 | * "I ask you, have you ever known what it is to be an orphan?" | 211 | * "I ask you, have you ever known what it is to be an orphan?" |
214 | */ | 212 | */ |
215 | static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task) | 213 | static int will_become_orphaned_pgrp(struct pid *pgrp, struct task_struct *ignored_task) |
216 | { | 214 | { |
217 | struct task_struct *p; | 215 | struct task_struct *p; |
218 | int ret = 1; | 216 | int ret = 1; |
219 | 217 | ||
220 | do_each_task_pid(pgrp, PIDTYPE_PGID, p) { | 218 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { |
221 | if (p == ignored_task | 219 | if (p == ignored_task |
222 | || p->exit_state | 220 | || p->exit_state |
223 | || is_init(p->real_parent)) | 221 | || is_init(p->real_parent)) |
224 | continue; | 222 | continue; |
225 | if (process_group(p->real_parent) != pgrp && | 223 | if (task_pgrp(p->real_parent) != pgrp && |
226 | process_session(p->real_parent) == process_session(p)) { | 224 | task_session(p->real_parent) == task_session(p)) { |
227 | ret = 0; | 225 | ret = 0; |
228 | break; | 226 | break; |
229 | } | 227 | } |
230 | } while_each_task_pid(pgrp, PIDTYPE_PGID, p); | 228 | } while_each_pid_task(pgrp, PIDTYPE_PGID, p); |
231 | return ret; /* (sighing) "Often!" */ | 229 | return ret; /* (sighing) "Often!" */ |
232 | } | 230 | } |
233 | 231 | ||
234 | int is_orphaned_pgrp(int pgrp) | 232 | int is_current_pgrp_orphaned(void) |
235 | { | 233 | { |
236 | int retval; | 234 | int retval; |
237 | 235 | ||
238 | read_lock(&tasklist_lock); | 236 | read_lock(&tasklist_lock); |
239 | retval = will_become_orphaned_pgrp(pgrp, NULL); | 237 | retval = will_become_orphaned_pgrp(task_pgrp(current), NULL); |
240 | read_unlock(&tasklist_lock); | 238 | read_unlock(&tasklist_lock); |
241 | 239 | ||
242 | return retval; | 240 | return retval; |
243 | } | 241 | } |
244 | 242 | ||
245 | static int has_stopped_jobs(int pgrp) | 243 | static int has_stopped_jobs(struct pid *pgrp) |
246 | { | 244 | { |
247 | int retval = 0; | 245 | int retval = 0; |
248 | struct task_struct *p; | 246 | struct task_struct *p; |
249 | 247 | ||
250 | do_each_task_pid(pgrp, PIDTYPE_PGID, p) { | 248 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { |
251 | if (p->state != TASK_STOPPED) | 249 | if (p->state != TASK_STOPPED) |
252 | continue; | 250 | continue; |
253 | retval = 1; | 251 | retval = 1; |
254 | break; | 252 | break; |
255 | } while_each_task_pid(pgrp, PIDTYPE_PGID, p); | 253 | } while_each_pid_task(pgrp, PIDTYPE_PGID, p); |
256 | return retval; | 254 | return retval; |
257 | } | 255 | } |
258 | 256 | ||
@@ -430,8 +428,10 @@ static void close_files(struct files_struct * files) | |||
430 | while (set) { | 428 | while (set) { |
431 | if (set & 1) { | 429 | if (set & 1) { |
432 | struct file * file = xchg(&fdt->fd[i], NULL); | 430 | struct file * file = xchg(&fdt->fd[i], NULL); |
433 | if (file) | 431 | if (file) { |
434 | filp_close(file, files); | 432 | filp_close(file, files); |
433 | cond_resched(); | ||
434 | } | ||
435 | } | 435 | } |
436 | i++; | 436 | i++; |
437 | set >>= 1; | 437 | set >>= 1; |
@@ -648,14 +648,14 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
648 | * than we are, and it was the only connection | 648 | * than we are, and it was the only connection |
649 | * outside, so the child pgrp is now orphaned. | 649 | * outside, so the child pgrp is now orphaned. |
650 | */ | 650 | */ |
651 | if ((process_group(p) != process_group(father)) && | 651 | if ((task_pgrp(p) != task_pgrp(father)) && |
652 | (process_session(p) == process_session(father))) { | 652 | (task_session(p) == task_session(father))) { |
653 | int pgrp = process_group(p); | 653 | struct pid *pgrp = task_pgrp(p); |
654 | 654 | ||
655 | if (will_become_orphaned_pgrp(pgrp, NULL) && | 655 | if (will_become_orphaned_pgrp(pgrp, NULL) && |
656 | has_stopped_jobs(pgrp)) { | 656 | has_stopped_jobs(pgrp)) { |
657 | __kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp); | 657 | __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp); |
658 | __kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp); | 658 | __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp); |
659 | } | 659 | } |
660 | } | 660 | } |
661 | } | 661 | } |
@@ -735,6 +735,7 @@ static void exit_notify(struct task_struct *tsk) | |||
735 | int state; | 735 | int state; |
736 | struct task_struct *t; | 736 | struct task_struct *t; |
737 | struct list_head ptrace_dead, *_p, *_n; | 737 | struct list_head ptrace_dead, *_p, *_n; |
738 | struct pid *pgrp; | ||
738 | 739 | ||
739 | if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT) | 740 | if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT) |
740 | && !thread_group_empty(tsk)) { | 741 | && !thread_group_empty(tsk)) { |
@@ -787,12 +788,13 @@ static void exit_notify(struct task_struct *tsk) | |||
787 | 788 | ||
788 | t = tsk->real_parent; | 789 | t = tsk->real_parent; |
789 | 790 | ||
790 | if ((process_group(t) != process_group(tsk)) && | 791 | pgrp = task_pgrp(tsk); |
791 | (process_session(t) == process_session(tsk)) && | 792 | if ((task_pgrp(t) != pgrp) && |
792 | will_become_orphaned_pgrp(process_group(tsk), tsk) && | 793 | (task_session(t) != task_session(tsk)) && |
793 | has_stopped_jobs(process_group(tsk))) { | 794 | will_become_orphaned_pgrp(pgrp, tsk) && |
794 | __kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk)); | 795 | has_stopped_jobs(pgrp)) { |
795 | __kill_pg_info(SIGCONT, SEND_SIG_PRIV, process_group(tsk)); | 796 | __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp); |
797 | __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp); | ||
796 | } | 798 | } |
797 | 799 | ||
798 | /* Let father know we died | 800 | /* Let father know we died |