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