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