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