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