|
|
1.1.1.2 root 1: /*
2: * linux/kernel/exit.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
1.1.1.4 root 7: #define DEBUG_PROC_TREE
8:
1.1 root 9: #include <errno.h>
10: #include <signal.h>
11: #include <sys/wait.h>
12:
13: #include <linux/sched.h>
14: #include <linux/kernel.h>
1.1.1.10! root 15: #include <linux/mm.h>
1.1 root 16: #include <linux/tty.h>
17: #include <asm/segment.h>
18:
19: int sys_close(int fd);
20:
1.1.1.8 root 21: int send_sig(long sig,struct task_struct * p,int priv)
1.1.1.5 root 22: {
23: if (!p || (sig < 0) || (sig > 32))
24: return -EINVAL;
1.1.1.8 root 25: if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
1.1.1.9 root 26: (current->euid != p->euid) && (current->uid != p->uid) && !suser())
1.1.1.5 root 27: return -EPERM;
28: if (!sig)
29: return 0;
30: if ((sig == SIGKILL) || (sig == SIGCONT)) {
31: if (p->state == TASK_STOPPED)
32: p->state = TASK_RUNNING;
33: p->exit_code = 0;
34: p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
35: (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
36: }
37: /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
38: if ((sig >= SIGSTOP) && (sig <= SIGTTOU))
39: p->signal &= ~(1<<(SIGCONT-1));
40: /* Actually deliver the signal */
41: p->signal |= (1<<(sig-1));
42: if (p->flags & PF_PTRACED) {
43: /* save the signal number for wait. */
44: p->exit_code = sig;
45:
1.1.1.9 root 46: /* we have to make sure the parent process is awake. */
1.1.1.5 root 47: if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
48: p->p_pptr->state = TASK_RUNNING;
49:
50: /* we have to make sure that the process stops. */
51: if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)
52: p->state = TASK_STOPPED;
53: }
54: return 0;
55: }
56:
1.1 root 57: void release(struct task_struct * p)
58: {
59: int i;
60:
61: if (!p)
62: return;
1.1.1.4 root 63: if (p == current) {
64: printk("task releasing itself\n\r");
65: return;
66: }
1.1 root 67: for (i=1 ; i<NR_TASKS ; i++)
1.1.1.7 root 68: if (task[i] == p) {
69: task[i] = NULL;
1.1.1.9 root 70: REMOVE_LINKS(p);
1.1.1.7 root 71: free_page((long) p);
1.1 root 72: return;
73: }
74: panic("trying to release non-existent task");
75: }
76:
1.1.1.4 root 77: #ifdef DEBUG_PROC_TREE
78: /*
79: * Check to see if a task_struct pointer is present in the task[] array
80: * Return 0 if found, and 1 if not found.
81: */
82: int bad_task_ptr(struct task_struct *p)
83: {
84: int i;
85:
86: if (!p)
87: return 0;
88: for (i=0 ; i<NR_TASKS ; i++)
89: if (task[i] == p)
90: return 0;
91: return 1;
92: }
93:
94: /*
95: * This routine scans the pid tree and make sure the rep invarient still
96: * holds. Used for debugging only, since it's very slow....
97: *
98: * It looks a lot scarier than it really is.... we're doing �nothing more
99: * than verifying the doubly-linked list found�in p_ysptr and p_osptr,
100: * and checking it corresponds with the process tree defined by p_cptr and
101: * p_pptr;
102: */
103: void audit_ptree()
104: {
105: int i;
106:
107: for (i=1 ; i<NR_TASKS ; i++) {
108: if (!task[i])
109: continue;
110: if (bad_task_ptr(task[i]->p_pptr))
111: printk("Warning, pid %d's parent link is bad\n",
112: task[i]->pid);
113: if (bad_task_ptr(task[i]->p_cptr))
114: printk("Warning, pid %d's child link is bad\n",
115: task[i]->pid);
116: if (bad_task_ptr(task[i]->p_ysptr))
117: printk("Warning, pid %d's ys link is bad\n",
118: task[i]->pid);
119: if (bad_task_ptr(task[i]->p_osptr))
120: printk("Warning, pid %d's os link is bad\n",
121: task[i]->pid);
122: if (task[i]->p_pptr == task[i])
123: printk("Warning, pid %d parent link points to self\n");
124: if (task[i]->p_cptr == task[i])
125: printk("Warning, pid %d child link points to self\n");
126: if (task[i]->p_ysptr == task[i])
127: printk("Warning, pid %d ys link points to self\n");
128: if (task[i]->p_osptr == task[i])
129: printk("Warning, pid %d os link points to self\n");
130: if (task[i]->p_osptr) {
131: if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
132: printk(
133: "Warning, pid %d older sibling %d parent is %d\n",
134: task[i]->pid, task[i]->p_osptr->pid,
135: task[i]->p_osptr->p_pptr->pid);
136: if (task[i]->p_osptr->p_ysptr != task[i])
137: printk(
138: "Warning, pid %d older sibling %d has mismatched ys link\n",
139: task[i]->pid, task[i]->p_osptr->pid);
140: }
141: if (task[i]->p_ysptr) {
142: if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
143: printk(
144: "Warning, pid %d younger sibling %d parent is %d\n",
145: task[i]->pid, task[i]->p_osptr->pid,
146: task[i]->p_osptr->p_pptr->pid);
147: if (task[i]->p_ysptr->p_osptr != task[i])
148: printk(
149: "Warning, pid %d younger sibling %d has mismatched os link\n",
150: task[i]->pid, task[i]->p_ysptr->pid);
151: }
152: if (task[i]->p_cptr) {
153: if (task[i]->p_cptr->p_pptr != task[i])
154: printk(
155: "Warning, pid %d youngest child %d has mismatched parent link\n",
156: task[i]->pid, task[i]->p_cptr->pid);
157: if (task[i]->p_cptr->p_ysptr)
158: printk(
159: "Warning, pid %d youngest child %d has non-NULL ys link\n",
160: task[i]->pid, task[i]->p_cptr->pid);
161: }
162: }
163: }
164: #endif /* DEBUG_PROC_TREE */
165:
1.1.1.8 root 166: /*
167: * This checks not only the pgrp, but falls back on the pid if no
168: * satisfactory prgp is found. I dunno - gdb doesn't work correctly
169: * without this...
170: */
1.1.1.4 root 171: int session_of_pgrp(int pgrp)
1.1.1.2 root 172: {
1.1.1.4 root 173: struct task_struct **p;
1.1.1.8 root 174: int fallback;
1.1.1.4 root 175:
1.1.1.8 root 176: fallback = -1;
177: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
178: if (!*p || (*p)->session <= 0)
179: continue;
1.1.1.4 root 180: if ((*p)->pgrp == pgrp)
1.1.1.8 root 181: return (*p)->session;
182: if ((*p)->pid == pgrp)
183: fallback = (*p)->session;
184: }
185: return fallback;
1.1.1.4 root 186: }
187:
188: int kill_pg(int pgrp, int sig, int priv)
189: {
190: struct task_struct **p;
191: int err,retval = -ESRCH;
192: int found = 0;
193:
1.1.1.5 root 194: if (sig<0 || sig>32 || pgrp<=0)
1.1.1.4 root 195: return -EINVAL;
196: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
1.1.1.8 root 197: if (*p && (*p)->pgrp == pgrp) {
1.1.1.4 root 198: if (sig && (err = send_sig(sig,*p,priv)))
199: retval = err;
200: else
201: found++;
202: }
203: return(found ? 0 : retval);
204: }
205:
206: int kill_proc(int pid, int sig, int priv)
207: {
208: struct task_struct **p;
209:
1.1.1.5 root 210: if (sig<0 || sig>32)
1.1.1.4 root 211: return -EINVAL;
212: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
1.1.1.8 root 213: if (*p && (*p)->pid == pid)
1.1.1.4 root 214: return(sig ? send_sig(sig,*p,priv) : 0);
215: return(-ESRCH);
1.1.1.2 root 216: }
217:
218: /*
1.1.1.4 root 219: * POSIX specifies that kill(-1,sig) is unspecified, but what we have
220: * is probably wrong. Should make it like BSD or SYSV.
1.1.1.2 root 221: */
222: int sys_kill(int pid,int sig)
1.1 root 223: {
224: struct task_struct **p = NR_TASKS + task;
1.1.1.7 root 225: int err, retval = 0, count = 0;
1.1 root 226:
1.1.1.4 root 227: if (!pid)
1.1.1.7 root 228: return(kill_pg(current->pgrp,sig,0));
1.1.1.4 root 229: if (pid == -1) {
230: while (--p > &FIRST_TASK)
1.1.1.8 root 231: if (*p && (*p)->pid > 1 && *p != current) {
1.1.1.7 root 232: ++count;
233: if ((err = send_sig(sig,*p,0)) != -EPERM)
234: retval = err;
235: }
236: return(count ? retval : -ESRCH);
1.1.1.4 root 237: }
238: if (pid < 0)
239: return(kill_pg(-pid,sig,0));
240: /* Normal kill */
241: return(kill_proc(pid,sig,0));
1.1 root 242: }
243:
1.1.1.4 root 244: /*
245: * Determine if a process group is "orphaned", according to the POSIX
246: * definition in 2.2.2.52. Orphaned process groups are not to be affected
247: * by terminal-generated stop signals. Newly orphaned process groups are
248: * to receive a SIGHUP and a SIGCONT.
249: *
250: * "I ask you, have you ever known what it is to be an orphan?"
251: */
252: int is_orphaned_pgrp(int pgrp)
1.1 root 253: {
1.1.1.4 root 254: struct task_struct **p;
1.1.1.2 root 255:
1.1.1.4 root 256: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
257: if (!(*p) ||
258: ((*p)->pgrp != pgrp) ||
259: ((*p)->state == TASK_ZOMBIE) ||
260: ((*p)->p_pptr->pid == 1))
261: continue;
262: if (((*p)->p_pptr->pgrp != pgrp) &&
263: ((*p)->p_pptr->session == (*p)->session))
264: return 0;
265: }
266: return(1); /* (sighing) "Often!" */
1.1 root 267: }
268:
1.1.1.4 root 269: static int has_stopped_jobs(int pgrp)
1.1 root 270: {
1.1.1.4 root 271: struct task_struct ** p;
272:
273: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
1.1.1.8 root 274: if (!*p || (*p)->pgrp != pgrp)
1.1.1.4 root 275: continue;
276: if ((*p)->state == TASK_STOPPED)
277: return(1);
278: }
279: return(0);
280: }
281:
1.1.1.9 root 282: static void forget_original_parent(struct task_struct * father)
283: {
284: struct task_struct ** p;
285:
286: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
287: if (*p && (*p)->p_opptr == father)
1.1.1.10! root 288: if (task[1])
! 289: (*p)->p_opptr = task[1];
! 290: else
! 291: (*p)->p_opptr = task[0];
1.1.1.9 root 292: }
293:
1.1.1.4 root 294: volatile void do_exit(long code)
295: {
296: struct task_struct *p;
1.1 root 297: int i;
298:
1.1.1.10! root 299: fake_volatile:
1.1 root 300: free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
301: free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
302: for (i=0 ; i<NR_OPEN ; i++)
303: if (current->filp[i])
304: sys_close(i);
1.1.1.9 root 305: forget_original_parent(current);
1.1 root 306: iput(current->pwd);
1.1.1.4 root 307: current->pwd = NULL;
1.1 root 308: iput(current->root);
1.1.1.4 root 309: current->root = NULL;
1.1.1.3 root 310: iput(current->executable);
1.1.1.4 root 311: current->executable = NULL;
1.1.1.8 root 312: for (i=0; i < current->numlibraries; i++) {
313: iput(current->libraries[i].library);
314: current->libraries[i].library = NULL;
315: }
1.1.1.2 root 316: current->state = TASK_ZOMBIE;
317: current->exit_code = code;
1.1.1.7 root 318: current->rss = 0;
1.1.1.4 root 319: /*
320: * Check to see if any process groups have become orphaned
321: * as a result of our exiting, and if they have any stopped
322: * jobs, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
323: *
324: * Case i: Our father is in a different pgrp than we are
325: * and we were the only connection outside, so our pgrp
326: * is about to become orphaned.
327: */
328: if ((current->p_pptr->pgrp != current->pgrp) &&
329: (current->p_pptr->session == current->session) &&
330: is_orphaned_pgrp(current->pgrp) &&
331: has_stopped_jobs(current->pgrp)) {
332: kill_pg(current->pgrp,SIGHUP,1);
333: kill_pg(current->pgrp,SIGCONT,1);
334: }
335: /* Let father know we died */
1.1.1.5 root 336: send_sig (SIGCHLD, current->p_pptr, 1);
1.1.1.4 root 337:
338: /*
339: * This loop does two things:
340: *
341: * A. Make init inherit all the child processes
342: * B. Check to see if any process groups have become orphaned
343: * as a result of our exiting, and if they have any stopped
1.1.1.9 root 344: * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
1.1.1.4 root 345: */
1.1.1.7 root 346: while (p = current->p_cptr) {
347: current->p_cptr = p->p_osptr;
348: p->p_ysptr = NULL;
1.1.1.9 root 349: p->flags &= ~PF_PTRACED;
1.1.1.10! root 350: if (task[1])
! 351: p->p_pptr = task[1];
! 352: else
! 353: p->p_pptr = task[0];
1.1.1.9 root 354: p->p_osptr = p->p_pptr->p_cptr;
355: p->p_osptr->p_ysptr = p;
356: p->p_pptr->p_cptr = p;
1.1.1.7 root 357: if (p->state == TASK_ZOMBIE)
1.1.1.10! root 358: send_sig(SIGCHLD,p->p_pptr,1);
1.1.1.7 root 359: /*
360: * process group orphan check
361: * Case ii: Our child is in a different pgrp
362: * than we are, and it was the only connection
363: * outside, so the child pgrp is now orphaned.
364: */
365: if ((p->pgrp != current->pgrp) &&
366: (p->session == current->session) &&
367: is_orphaned_pgrp(p->pgrp) &&
368: has_stopped_jobs(p->pgrp)) {
369: kill_pg(p->pgrp,SIGHUP,1);
370: kill_pg(p->pgrp,SIGCONT,1);
1.1.1.4 root 371: }
372: }
373: if (current->leader) {
374: struct task_struct **p;
375: struct tty_struct *tty;
376:
377: if (current->tty >= 0) {
378: tty = TTY_TABLE(current->tty);
1.1.1.6 root 379: if (tty->pgrp > 0)
1.1.1.4 root 380: kill_pg(tty->pgrp, SIGHUP, 1);
1.1.1.6 root 381: tty->pgrp = -1;
1.1.1.4 root 382: tty->session = 0;
383: }
384: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
1.1.1.8 root 385: if (*p && (*p)->session == current->session)
1.1.1.4 root 386: (*p)->tty = -1;
387: }
388: if (last_task_used_math == current)
389: last_task_used_math = NULL;
390: #ifdef DEBUG_PROC_TREE
391: audit_ptree();
392: #endif
1.1 root 393: schedule();
1.1.1.10! root 394: /*
! 395: * In order to get rid of the "volatile function does return" message
! 396: * I did this little loop that confuses gcc to think do_exit really
! 397: * is volatile. In fact it's schedule() that is volatile in some
! 398: * circumstances: when current->state = ZOMBIE, schedule() never
! 399: * returns.
! 400: *
! 401: * In fact the natural way to do all this is to have the label and the
! 402: * goto right after each other, but I put the fake_volatile label at
! 403: * the start of the function just in case something /really/ bad
! 404: * happens, and the schedule returns. This way we can try again. I'm
! 405: * not paranoid: it's just that everybody is out to get me.
! 406: */
! 407: goto fake_volatile;
1.1 root 408: }
409:
410: int sys_exit(int error_code)
411: {
1.1.1.4 root 412: do_exit((error_code&0xff)<<8);
1.1 root 413: }
414:
1.1.1.2 root 415: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
1.1 root 416: {
1.1.1.4 root 417: int flag;
418: struct task_struct *p;
419: unsigned long oldblocked;
1.1 root 420:
1.1.1.5 root 421: if (stat_addr)
422: verify_area(stat_addr,4);
1.1 root 423: repeat:
1.1.1.2 root 424: flag=0;
1.1.1.9 root 425: for (p = current->p_cptr ; p ; p = p->p_osptr) {
1.1.1.2 root 426: if (pid>0) {
1.1.1.4 root 427: if (p->pid != pid)
1.1.1.2 root 428: continue;
429: } else if (!pid) {
1.1.1.4 root 430: if (p->pgrp != current->pgrp)
1.1.1.2 root 431: continue;
432: } else if (pid != -1) {
1.1.1.4 root 433: if (p->pgrp != -pid)
1.1.1.2 root 434: continue;
435: }
1.1.1.4 root 436: switch (p->state) {
1.1.1.2 root 437: case TASK_STOPPED:
1.1.1.8 root 438: if (!p->exit_code)
439: continue;
440: if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
1.1.1.2 root 441: continue;
1.1.1.5 root 442: if (stat_addr)
443: put_fs_long((p->exit_code << 8) | 0x7f,
444: stat_addr);
1.1.1.4 root 445: p->exit_code = 0;
446: return p->pid;
1.1.1.2 root 447: case TASK_ZOMBIE:
1.1.1.7 root 448: current->cutime += p->utime + p->cutime;
449: current->cstime += p->stime + p->cstime;
450: current->cmin_flt += p->min_flt + p->cmin_flt;
451: current->cmaj_flt += p->maj_flt + p->cmaj_flt;
1.1.1.4 root 452: flag = p->pid;
1.1.1.5 root 453: if (stat_addr)
454: put_fs_long(p->exit_code, stat_addr);
1.1.1.9 root 455: if (p->p_opptr != p->p_pptr) {
456: REMOVE_LINKS(p);
457: p->p_pptr = p->p_opptr;
458: SET_LINKS(p);
459: send_sig(SIGCHLD,p->p_pptr,1);
460: } else
461: release(p);
1.1.1.4 root 462: #ifdef DEBUG_PROC_TREE
463: audit_ptree();
464: #endif
1.1.1.2 root 465: return flag;
466: default:
1.1 root 467: flag=1;
1.1.1.2 root 468: continue;
469: }
470: }
1.1 root 471: if (flag) {
472: if (options & WNOHANG)
473: return 0;
1.1.1.2 root 474: current->state=TASK_INTERRUPTIBLE;
1.1.1.4 root 475: oldblocked = current->blocked;
476: current->blocked &= ~(1<<(SIGCHLD-1));
1.1.1.2 root 477: schedule();
1.1.1.4 root 478: current->blocked = oldblocked;
479: if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
480: return -ERESTARTSYS;
1.1 root 481: else
1.1.1.4 root 482: goto repeat;
1.1 root 483: }
484: return -ECHILD;
485: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.