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