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