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