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 for (i=0; i<current->numlibraries; i++) {
291 iput(current->libraries[i].library);
292 current->libraries[i].library = NULL;
293 }
294 current->state = TASK_ZOMBIE;
295 current->exit_code = code;
296 current->rss = 0;
297
298
299
300
301
302
303
304
305
306 if ((current->p_pptr->pgrp != current->pgrp) &&
307 (current->p_pptr->session == current->session) &&
308 is_orphaned_pgrp(current->pgrp) &&
309 has_stopped_jobs(current->pgrp)) {
310 kill_pg(current->pgrp,SIGHUP,1);
311 kill_pg(current->pgrp,SIGCONT,1);
312 }
313
314 send_sig (SIGCHLD, current->p_pptr, 1);
315
316
317
318
319
320
321
322
323
324 while (p = current->p_cptr) {
325 current->p_cptr = p->p_osptr;
326 p->p_ysptr = NULL;
327 p->flags &= ~PF_PTRACED;
328 p->p_pptr = task[1];
329 p->p_osptr = task[1]->p_cptr;
330 task[1]->p_cptr->p_ysptr = p;
331 task[1]->p_cptr = p;
332 if (p->state == TASK_ZOMBIE)
333 task[1]->signal |= (1<<(SIGCHLD-1));
334
335
336
337
338
339
340 if ((p->pgrp != current->pgrp) &&
341 (p->session == current->session) &&
342 is_orphaned_pgrp(p->pgrp) &&
343 has_stopped_jobs(p->pgrp)) {
344 kill_pg(p->pgrp,SIGHUP,1);
345 kill_pg(p->pgrp,SIGCONT,1);
346 }
347 }
348 if (current->leader) {
349 struct task_struct **p;
350 struct tty_struct *tty;
351
352 if (current->tty >= 0) {
353 tty = TTY_TABLE(current->tty);
354 if (tty->pgrp > 0)
355 kill_pg(tty->pgrp, SIGHUP, 1);
356 tty->pgrp = -1;
357 tty->session = 0;
358 }
359 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
360 if ((*p)->session == current->session)
361 (*p)->tty = -1;
362 }
363 if (last_task_used_math == current)
364 last_task_used_math = NULL;
365 #ifdef DEBUG_PROC_TREE
366 audit_ptree();
367 #endif
368 schedule();
369 }
370
371 int sys_exit(int error_code)
372 {
373 do_exit((error_code&0xff)<<8);
374 }
375
376 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
377 {
378 int flag;
379 struct task_struct *p;
380 unsigned long oldblocked;
381
382 if (stat_addr)
383 verify_area(stat_addr,4);
384 repeat:
385 flag=0;
386 for (p = current->p_cptr ; p ; p = p->p_osptr) {
387 if (pid>0) {
388 if (p->pid != pid)
389 continue;
390 } else if (!pid) {
391 if (p->pgrp != current->pgrp)
392 continue;
393 } else if (pid != -1) {
394 if (p->pgrp != -pid)
395 continue;
396 }
397 switch (p->state) {
398 case TASK_STOPPED:
399 if (!(options & WUNTRACED) ||
400 !p->exit_code)
401 continue;
402 if (stat_addr)
403 put_fs_long((p->exit_code << 8) | 0x7f,
404 stat_addr);
405 p->exit_code = 0;
406 return p->pid;
407 case TASK_ZOMBIE:
408 current->cutime += p->utime + p->cutime;
409 current->cstime += p->stime + p->cstime;
410 current->cmin_flt += p->min_flt + p->cmin_flt;
411 current->cmaj_flt += p->maj_flt + p->cmaj_flt;
412 flag = p->pid;
413 if (stat_addr)
414 put_fs_long(p->exit_code, stat_addr);
415 release(p);
416 #ifdef DEBUG_PROC_TREE
417 audit_ptree();
418 #endif
419 return flag;
420 default:
421 flag=1;
422 continue;
423 }
424 }
425 if (flag) {
426 if (options & WNOHANG)
427 return 0;
428 current->state=TASK_INTERRUPTIBLE;
429 oldblocked = current->blocked;
430 current->blocked &= ~(1<<(SIGCHLD-1));
431 schedule();
432 current->blocked = oldblocked;
433 if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
434 return -ERESTARTSYS;
435 else
436 goto repeat;
437 }
438 return -ECHILD;
439 }
440
441