This source file includes following definitions.
- generate
- send_sig
- notify_parent
- release
- bad_task_ptr
- audit_ptree
- session_of_pgrp
- kill_pg
- kill_sl
- kill_proc
- sys_kill
- is_orphaned_pgrp
- has_stopped_jobs
- forget_original_parent
- __exit_files
- exit_files
- __exit_fs
- exit_fs
- __exit_sighand
- exit_sighand
- exit_mm
- exit_notify
- do_exit
- sys_exit
- sys_wait4
- sys_waitpid
1
2
3
4
5
6
7 #undef DEBUG_PROC_TREE
8
9 #include <linux/wait.h>
10 #include <linux/errno.h>
11 #include <linux/signal.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/resource.h>
15 #include <linux/mm.h>
16 #include <linux/tty.h>
17 #include <linux/malloc.h>
18
19 #include <asm/segment.h>
20 #include <asm/pgtable.h>
21
22 extern void sem_exit (void);
23 extern void acct_process (long exitcode);
24 extern void kerneld_exit(void);
25
26 int getrusage(struct task_struct *, int, struct rusage *);
27
28 static inline void generate(unsigned long sig, struct task_struct * p)
29 {
30 unsigned long mask = 1 << (sig-1);
31 struct sigaction * sa = sig + p->sig->action - 1;
32
33
34
35
36
37
38 if (!(mask & p->blocked) && !(p->flags & PF_PTRACED)) {
39
40 if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
41 return;
42
43 if ((sa->sa_handler == SIG_DFL) &&
44 (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH || sig == SIGURG))
45 return;
46 }
47 p->signal |= mask;
48 if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
49 wake_up_process(p);
50 }
51
52 int send_sig(unsigned long sig,struct task_struct * p,int priv)
53 {
54 if (!p || sig > 32)
55 return -EINVAL;
56 if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
57 (current->euid ^ p->euid) && (current->euid ^ p->uid) &&
58 (current->uid ^ p->euid) && (current->uid ^ p->uid) &&
59 !suser())
60 return -EPERM;
61 if (!sig)
62 return 0;
63
64
65
66 if (!p->sig)
67 return 0;
68 if ((sig == SIGKILL) || (sig == SIGCONT)) {
69 if (p->state == TASK_STOPPED)
70 wake_up_process(p);
71 p->exit_code = 0;
72 p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
73 (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
74 }
75 if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
76 p->signal &= ~(1<<(SIGCONT-1));
77
78 generate(sig,p);
79 return 0;
80 }
81
82 void notify_parent(struct task_struct * tsk)
83 {
84 if (tsk->p_pptr == task[smp_num_cpus])
85 tsk->exit_signal = SIGCHLD;
86 send_sig(tsk->exit_signal, tsk->p_pptr, 1);
87 wake_up_interruptible(&tsk->p_pptr->wait_chldexit);
88 }
89
90 void release(struct task_struct * p)
91 {
92 int i;
93
94 if (!p)
95 return;
96 if (p == current) {
97 printk("task releasing itself\n");
98 return;
99 }
100 for (i=1 ; i<NR_TASKS ; i++)
101 if (task[i] == p) {
102 nr_tasks--;
103 task[i] = NULL;
104 REMOVE_LINKS(p);
105 release_thread(p);
106 if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page)
107 printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm);
108 free_kernel_stack(p->kernel_stack_page);
109 current->cmin_flt += p->min_flt + p->cmin_flt;
110 current->cmaj_flt += p->maj_flt + p->cmaj_flt;
111 current->cnswap += p->nswap + p->cnswap;
112 kfree(p);
113 return;
114 }
115 panic("trying to release non-existent task");
116 }
117
118 #ifdef DEBUG_PROC_TREE
119
120
121
122
123 int bad_task_ptr(struct task_struct *p)
124 {
125 int i;
126
127 if (!p)
128 return 0;
129 for (i=0 ; i<NR_TASKS ; i++)
130 if (task[i] == p)
131 return 0;
132 return 1;
133 }
134
135
136
137
138
139
140
141
142
143
144 void audit_ptree(void)
145 {
146 int i;
147
148 for (i=1 ; i<NR_TASKS ; i++) {
149 if (!task[i])
150 continue;
151 if (bad_task_ptr(task[i]->p_pptr))
152 printk("Warning, pid %d's parent link is bad\n",
153 task[i]->pid);
154 if (bad_task_ptr(task[i]->p_cptr))
155 printk("Warning, pid %d's child link is bad\n",
156 task[i]->pid);
157 if (bad_task_ptr(task[i]->p_ysptr))
158 printk("Warning, pid %d's ys link is bad\n",
159 task[i]->pid);
160 if (bad_task_ptr(task[i]->p_osptr))
161 printk("Warning, pid %d's os link is bad\n",
162 task[i]->pid);
163 if (task[i]->p_pptr == task[i])
164 printk("Warning, pid %d parent link points to self\n",
165 task[i]->pid);
166 if (task[i]->p_cptr == task[i])
167 printk("Warning, pid %d child link points to self\n",
168 task[i]->pid);
169 if (task[i]->p_ysptr == task[i])
170 printk("Warning, pid %d ys link points to self\n",
171 task[i]->pid);
172 if (task[i]->p_osptr == task[i])
173 printk("Warning, pid %d os link points to self\n",
174 task[i]->pid);
175 if (task[i]->p_osptr) {
176 if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
177 printk(
178 "Warning, pid %d older sibling %d parent is %d\n",
179 task[i]->pid, task[i]->p_osptr->pid,
180 task[i]->p_osptr->p_pptr->pid);
181 if (task[i]->p_osptr->p_ysptr != task[i])
182 printk(
183 "Warning, pid %d older sibling %d has mismatched ys link\n",
184 task[i]->pid, task[i]->p_osptr->pid);
185 }
186 if (task[i]->p_ysptr) {
187 if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
188 printk(
189 "Warning, pid %d younger sibling %d parent is %d\n",
190 task[i]->pid, task[i]->p_osptr->pid,
191 task[i]->p_osptr->p_pptr->pid);
192 if (task[i]->p_ysptr->p_osptr != task[i])
193 printk(
194 "Warning, pid %d younger sibling %d has mismatched os link\n",
195 task[i]->pid, task[i]->p_ysptr->pid);
196 }
197 if (task[i]->p_cptr) {
198 if (task[i]->p_cptr->p_pptr != task[i])
199 printk(
200 "Warning, pid %d youngest child %d has mismatched parent link\n",
201 task[i]->pid, task[i]->p_cptr->pid);
202 if (task[i]->p_cptr->p_ysptr)
203 printk(
204 "Warning, pid %d youngest child %d has non-NULL ys link\n",
205 task[i]->pid, task[i]->p_cptr->pid);
206 }
207 }
208 }
209 #endif
210
211
212
213
214
215
216 int session_of_pgrp(int pgrp)
217 {
218 struct task_struct *p;
219 int fallback;
220
221 fallback = -1;
222 for_each_task(p) {
223 if (p->session <= 0)
224 continue;
225 if (p->pgrp == pgrp)
226 return p->session;
227 if (p->pid == pgrp)
228 fallback = p->session;
229 }
230 return fallback;
231 }
232
233
234
235
236
237 int kill_pg(int pgrp, int sig, int priv)
238 {
239 struct task_struct *p;
240 int err,retval = -ESRCH;
241 int found = 0;
242
243 if (sig<0 || sig>32 || pgrp<=0)
244 return -EINVAL;
245 for_each_task(p) {
246 if (p->pgrp == pgrp) {
247 if ((err = send_sig(sig,p,priv)) != 0)
248 retval = err;
249 else
250 found++;
251 }
252 }
253 return(found ? 0 : retval);
254 }
255
256
257
258
259
260
261 int kill_sl(int sess, int sig, int priv)
262 {
263 struct task_struct *p;
264 int err,retval = -ESRCH;
265 int found = 0;
266
267 if (sig<0 || sig>32 || sess<=0)
268 return -EINVAL;
269 for_each_task(p) {
270 if (p->session == sess && p->leader) {
271 if ((err = send_sig(sig,p,priv)) != 0)
272 retval = err;
273 else
274 found++;
275 }
276 }
277 return(found ? 0 : retval);
278 }
279
280 int kill_proc(int pid, int sig, int priv)
281 {
282 struct task_struct *p;
283
284 if (sig<0 || sig>32)
285 return -EINVAL;
286 for_each_task(p) {
287 if (p && p->pid == pid)
288 return send_sig(sig,p,priv);
289 }
290 return(-ESRCH);
291 }
292
293
294
295
296
297 asmlinkage int sys_kill(int pid,int sig)
298 {
299 int err, retval = 0, count = 0;
300
301 if (!pid)
302 return(kill_pg(current->pgrp,sig,0));
303 if (pid == -1) {
304 struct task_struct * p;
305 for_each_task(p) {
306 if (p->pid > 1 && p != current) {
307 ++count;
308 if ((err = send_sig(sig,p,0)) != -EPERM)
309 retval = err;
310 }
311 }
312 return(count ? retval : -ESRCH);
313 }
314 if (pid < 0)
315 return(kill_pg(-pid,sig,0));
316
317 return(kill_proc(pid,sig,0));
318 }
319
320
321
322
323
324
325
326
327
328 int is_orphaned_pgrp(int pgrp)
329 {
330 struct task_struct *p;
331
332 for_each_task(p) {
333 if ((p->pgrp != pgrp) ||
334 (p->state == TASK_ZOMBIE) ||
335 (p->p_pptr->pid == 1))
336 continue;
337 if ((p->p_pptr->pgrp != pgrp) &&
338 (p->p_pptr->session == p->session))
339 return 0;
340 }
341 return(1);
342 }
343
344 static inline int has_stopped_jobs(int pgrp)
345 {
346 struct task_struct * p;
347
348 for_each_task(p) {
349 if (p->pgrp != pgrp)
350 continue;
351 if (p->state == TASK_STOPPED)
352 return(1);
353 }
354 return(0);
355 }
356
357 static inline void forget_original_parent(struct task_struct * father)
358 {
359 struct task_struct * p;
360
361 for_each_task(p) {
362 if (p->p_opptr == father)
363 if (task[smp_num_cpus])
364 p->p_opptr = task[smp_num_cpus];
365 else
366 p->p_opptr = task[0];
367 }
368 }
369
370 static inline void __exit_files(struct task_struct *tsk)
371 {
372 struct files_struct * files = tsk->files;
373
374 if (files) {
375 tsk->files = NULL;
376 if (!--files->count) {
377 int i;
378 for (i=0 ; i<NR_OPEN ; i++) {
379 struct file * filp = files->fd[i];
380 if (!filp)
381 continue;
382 files->fd[i] = NULL;
383 close_fp(filp);
384 }
385 kfree(files);
386 }
387 }
388 }
389
390 void exit_files(struct task_struct *tsk)
391 {
392 __exit_files(tsk);
393 }
394
395 static inline void __exit_fs(struct task_struct *tsk)
396 {
397 struct fs_struct * fs = tsk->fs;
398
399 if (fs) {
400 tsk->fs = NULL;
401 if (!--fs->count) {
402 iput(fs->root);
403 iput(fs->pwd);
404 kfree(fs);
405 }
406 }
407 }
408
409 void exit_fs(struct task_struct *tsk)
410 {
411 __exit_fs(tsk);
412 }
413
414 static inline void __exit_sighand(struct task_struct *tsk)
415 {
416 struct signal_struct * sig = tsk->sig;
417
418 if (sig) {
419 tsk->sig = NULL;
420 if (!--sig->count) {
421 kfree(sig);
422 }
423 }
424 }
425
426 void exit_sighand(struct task_struct *tsk)
427 {
428 __exit_sighand(tsk);
429 }
430
431 static inline void exit_mm(void)
432 {
433 struct mm_struct * mm = current->mm;
434
435
436 if (mm != &init_mm) {
437 flush_cache_mm(mm);
438 flush_tlb_mm(mm);
439 current->mm = &init_mm;
440 current->swappable = 0;
441 SET_PAGE_DIR(current, swapper_pg_dir);
442
443
444 if (!--mm->count) {
445 exit_mmap(mm);
446 free_page_tables(mm);
447 kfree(mm);
448 }
449 }
450 }
451
452
453
454
455
456 static void exit_notify(void)
457 {
458 struct task_struct * p;
459
460 forget_original_parent(current);
461
462
463
464
465
466
467
468
469
470 if ((current->p_pptr->pgrp != current->pgrp) &&
471 (current->p_pptr->session == current->session) &&
472 is_orphaned_pgrp(current->pgrp) &&
473 has_stopped_jobs(current->pgrp)) {
474 kill_pg(current->pgrp,SIGHUP,1);
475 kill_pg(current->pgrp,SIGCONT,1);
476 }
477
478 notify_parent(current);
479
480
481
482
483
484
485
486
487
488 while ((p = current->p_cptr) != NULL) {
489 current->p_cptr = p->p_osptr;
490 p->p_ysptr = NULL;
491 p->flags &= ~(PF_PTRACED|PF_TRACESYS);
492 if (task[smp_num_cpus] && task[smp_num_cpus] != current)
493 p->p_pptr = task[smp_num_cpus];
494 else
495 p->p_pptr = task[0];
496 p->p_osptr = p->p_pptr->p_cptr;
497 p->p_osptr->p_ysptr = p;
498 p->p_pptr->p_cptr = p;
499 if (p->state == TASK_ZOMBIE)
500 notify_parent(p);
501
502
503
504
505
506
507 if ((p->pgrp != current->pgrp) &&
508 (p->session == current->session) &&
509 is_orphaned_pgrp(p->pgrp) &&
510 has_stopped_jobs(p->pgrp)) {
511 kill_pg(p->pgrp,SIGHUP,1);
512 kill_pg(p->pgrp,SIGCONT,1);
513 }
514 }
515 if (current->leader)
516 disassociate_ctty(1);
517 }
518
519 NORET_TYPE void do_exit(long code)
520 {
521 if (intr_count) {
522 printk("Aiee, killing interrupt handler\n");
523 intr_count = 0;
524 }
525 fake_volatile:
526 acct_process(code);
527 current->flags |= PF_EXITING;
528 del_timer(¤t->real_timer);
529 sem_exit();
530 kerneld_exit();
531 exit_mm();
532 __exit_files(current);
533 __exit_fs(current);
534 __exit_sighand(current);
535 exit_thread();
536 current->state = TASK_ZOMBIE;
537 current->exit_code = code;
538 exit_notify();
539 #ifdef DEBUG_PROC_TREE
540 audit_ptree();
541 #endif
542 if (current->exec_domain && current->exec_domain->use_count)
543 (*current->exec_domain->use_count)--;
544 if (current->binfmt && current->binfmt->use_count)
545 (*current->binfmt->use_count)--;
546 schedule();
547
548
549
550
551
552
553
554
555
556
557
558
559
560 goto fake_volatile;
561 }
562
563 asmlinkage int sys_exit(int error_code)
564 {
565 do_exit((error_code&0xff)<<8);
566 }
567
568 asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru)
569 {
570 int flag, retval;
571 struct wait_queue wait = { current, NULL };
572 struct task_struct *p;
573
574 if (stat_addr) {
575 flag = verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr));
576 if (flag)
577 return flag;
578 }
579 if (ru) {
580 flag = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
581 if (flag)
582 return flag;
583 }
584 add_wait_queue(¤t->wait_chldexit,&wait);
585 repeat:
586 flag=0;
587 for (p = current->p_cptr ; p ; p = p->p_osptr) {
588 if (pid>0) {
589 if (p->pid != pid)
590 continue;
591 } else if (!pid) {
592 if (p->pgrp != current->pgrp)
593 continue;
594 } else if (pid != -1) {
595 if (p->pgrp != -pid)
596 continue;
597 }
598
599 if ((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
600 continue;
601 flag = 1;
602 switch (p->state) {
603 case TASK_STOPPED:
604 if (!p->exit_code)
605 continue;
606 if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
607 continue;
608 if (ru != NULL)
609 getrusage(p, RUSAGE_BOTH, ru);
610 if (stat_addr)
611 put_user((p->exit_code << 8) | 0x7f,
612 stat_addr);
613 p->exit_code = 0;
614 retval = p->pid;
615 goto end_wait4;
616 case TASK_ZOMBIE:
617 current->cutime += p->utime + p->cutime;
618 current->cstime += p->stime + p->cstime;
619 if (ru != NULL)
620 getrusage(p, RUSAGE_BOTH, ru);
621 if (stat_addr)
622 put_user(p->exit_code, stat_addr);
623 retval = p->pid;
624 if (p->p_opptr != p->p_pptr) {
625 REMOVE_LINKS(p);
626 p->p_pptr = p->p_opptr;
627 SET_LINKS(p);
628 notify_parent(p);
629 } else
630 release(p);
631 #ifdef DEBUG_PROC_TREE
632 audit_ptree();
633 #endif
634 goto end_wait4;
635 default:
636 continue;
637 }
638 }
639 if (flag) {
640 retval = 0;
641 if (options & WNOHANG)
642 goto end_wait4;
643 current->state=TASK_INTERRUPTIBLE;
644 schedule();
645 current->signal &= ~(1<<(SIGCHLD-1));
646 retval = -ERESTARTSYS;
647 if (current->signal & ~current->blocked)
648 goto end_wait4;
649 goto repeat;
650 }
651 retval = -ECHILD;
652 end_wait4:
653 remove_wait_queue(¤t->wait_chldexit,&wait);
654 return retval;
655 }
656
657 #ifndef __alpha__
658
659
660
661
662
663 asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options)
664 {
665 return sys_wait4(pid, stat_addr, options, NULL);
666 }
667
668 #endif