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