|
|
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>
15: #include <linux/tty.h>
16: #include <asm/segment.h>
17:
18: int sys_close(int fd);
19:
1.1.1.8 ! root 20: int send_sig(long sig,struct task_struct * p,int priv)
1.1.1.5 root 21: {
22: if (!p || (sig < 0) || (sig > 32))
23: return -EINVAL;
1.1.1.8 ! root 24: if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
! 25: (current->euid != p->euid) && !suser())
1.1.1.5 root 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: /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
37: if ((sig >= SIGSTOP) && (sig <= SIGTTOU))
38: p->signal &= ~(1<<(SIGCONT-1));
39: /* Actually deliver the signal */
40: p->signal |= (1<<(sig-1));
41: if (p->flags & PF_PTRACED) {
42: /* save the signal number for wait. */
43: p->exit_code = sig;
44:
45: /* we have to make sure the parent is awake. */
46: if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
47: p->p_pptr->state = TASK_RUNNING;
48:
49: /* we have to make sure that the process stops. */
50: if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)
51: p->state = TASK_STOPPED;
52: }
53: return 0;
54: }
55:
1.1 root 56: void release(struct task_struct * p)
57: {
58: int i;
59:
60: if (!p)
61: return;
1.1.1.4 root 62: if (p == current) {
63: printk("task releasing itself\n\r");
64: return;
65: }
1.1 root 66: for (i=1 ; i<NR_TASKS ; i++)
1.1.1.7 root 67: if (task[i] == p) {
68: task[i] = NULL;
1.1.1.4 root 69: /* Update links */
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;
1.1.1.7 root 76: free_page((long) p);
1.1 root 77: return;
78: }
79: panic("trying to release non-existent task");
80: }
81:
1.1.1.4 root 82: #ifdef DEBUG_PROC_TREE
83: /*
84: * Check to see if a task_struct pointer is present in the task[] array
85: * Return 0 if found, and 1 if not found.
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: * This routine scans the pid tree and make sure the rep invarient still
101: * holds. Used for debugging only, since it's very slow....
102: *
103: * It looks a lot scarier than it really is.... we're doing �nothing more
104: * than verifying the doubly-linked list found�in p_ysptr and p_osptr,
105: * and checking it corresponds with the process tree defined by p_cptr and
106: * p_pptr;
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 /* DEBUG_PROC_TREE */
170:
1.1.1.8 ! root 171: /*
! 172: * This checks not only the pgrp, but falls back on the pid if no
! 173: * satisfactory prgp is found. I dunno - gdb doesn't work correctly
! 174: * without this...
! 175: */
1.1.1.4 root 176: int session_of_pgrp(int pgrp)
1.1.1.2 root 177: {
1.1.1.4 root 178: struct task_struct **p;
1.1.1.8 ! root 179: int fallback;
1.1.1.4 root 180:
1.1.1.8 ! root 181: fallback = -1;
! 182: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
! 183: if (!*p || (*p)->session <= 0)
! 184: continue;
1.1.1.4 root 185: if ((*p)->pgrp == pgrp)
1.1.1.8 ! root 186: return (*p)->session;
! 187: if ((*p)->pid == pgrp)
! 188: fallback = (*p)->session;
! 189: }
! 190: return fallback;
1.1.1.4 root 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:
1.1.1.5 root 199: if (sig<0 || sig>32 || pgrp<=0)
1.1.1.4 root 200: return -EINVAL;
201: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
1.1.1.8 ! root 202: if (*p && (*p)->pgrp == pgrp) {
1.1.1.4 root 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:
1.1.1.5 root 215: if (sig<0 || sig>32)
1.1.1.4 root 216: return -EINVAL;
217: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
1.1.1.8 ! root 218: if (*p && (*p)->pid == pid)
1.1.1.4 root 219: return(sig ? send_sig(sig,*p,priv) : 0);
220: return(-ESRCH);
1.1.1.2 root 221: }
222:
223: /*
1.1.1.4 root 224: * POSIX specifies that kill(-1,sig) is unspecified, but what we have
225: * is probably wrong. Should make it like BSD or SYSV.
1.1.1.2 root 226: */
227: int sys_kill(int pid,int sig)
1.1 root 228: {
229: struct task_struct **p = NR_TASKS + task;
1.1.1.7 root 230: int err, retval = 0, count = 0;
1.1 root 231:
1.1.1.4 root 232: if (!pid)
1.1.1.7 root 233: return(kill_pg(current->pgrp,sig,0));
1.1.1.4 root 234: if (pid == -1) {
235: while (--p > &FIRST_TASK)
1.1.1.8 ! root 236: if (*p && (*p)->pid > 1 && *p != current) {
1.1.1.7 root 237: ++count;
238: if ((err = send_sig(sig,*p,0)) != -EPERM)
239: retval = err;
240: }
241: return(count ? retval : -ESRCH);
1.1.1.4 root 242: }
243: if (pid < 0)
244: return(kill_pg(-pid,sig,0));
245: /* Normal kill */
246: return(kill_proc(pid,sig,0));
1.1 root 247: }
248:
1.1.1.4 root 249: /*
250: * Determine if a process group is "orphaned", according to the POSIX
251: * definition in 2.2.2.52. Orphaned process groups are not to be affected
252: * by terminal-generated stop signals. Newly orphaned process groups are
253: * to receive a SIGHUP and a SIGCONT.
254: *
255: * "I ask you, have you ever known what it is to be an orphan?"
256: */
257: int is_orphaned_pgrp(int pgrp)
1.1 root 258: {
1.1.1.4 root 259: struct task_struct **p;
1.1.1.2 root 260:
1.1.1.4 root 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); /* (sighing) "Often!" */
1.1 root 272: }
273:
1.1.1.4 root 274: static int has_stopped_jobs(int pgrp)
1.1 root 275: {
1.1.1.4 root 276: struct task_struct ** p;
277:
278: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
1.1.1.8 ! root 279: if (!*p || (*p)->pgrp != pgrp)
1.1.1.4 root 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;
1.1 root 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);
1.1.1.4 root 298: current->pwd = NULL;
1.1 root 299: iput(current->root);
1.1.1.4 root 300: current->root = NULL;
1.1.1.3 root 301: iput(current->executable);
1.1.1.4 root 302: current->executable = NULL;
1.1.1.8 ! root 303: for (i=0; i < current->numlibraries; i++) {
! 304: iput(current->libraries[i].library);
! 305: current->libraries[i].library = NULL;
! 306: }
1.1.1.2 root 307: current->state = TASK_ZOMBIE;
308: current->exit_code = code;
1.1.1.7 root 309: current->rss = 0;
1.1.1.4 root 310: /*
311: * Check to see if any process groups have become orphaned
312: * as a result of our exiting, and if they have any stopped
313: * jobs, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
314: *
315: * Case i: Our father is in a different pgrp than we are
316: * and we were the only connection outside, so our pgrp
317: * is about to become orphaned.
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: /* Let father know we died */
1.1.1.5 root 327: send_sig (SIGCHLD, current->p_pptr, 1);
1.1.1.4 root 328:
329: /*
330: * This loop does two things:
331: *
332: * A. Make init inherit all the child processes
333: * B. Check to see if any process groups have become orphaned
334: * as a result of our exiting, and if they have any stopped
335: * jons, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
336: */
1.1.1.7 root 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: * process group orphan check
349: * Case ii: Our child is in a different pgrp
350: * than we are, and it was the only connection
351: * outside, so the child pgrp is now orphaned.
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);
1.1.1.4 root 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);
1.1.1.6 root 367: if (tty->pgrp > 0)
1.1.1.4 root 368: kill_pg(tty->pgrp, SIGHUP, 1);
1.1.1.6 root 369: tty->pgrp = -1;
1.1.1.4 root 370: tty->session = 0;
371: }
372: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
1.1.1.8 ! root 373: if (*p && (*p)->session == current->session)
1.1.1.4 root 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
1.1 root 381: schedule();
382: }
383:
384: int sys_exit(int error_code)
385: {
1.1.1.4 root 386: do_exit((error_code&0xff)<<8);
1.1 root 387: }
388:
1.1.1.2 root 389: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
1.1 root 390: {
1.1.1.4 root 391: int flag;
392: struct task_struct *p;
393: unsigned long oldblocked;
1.1 root 394:
1.1.1.5 root 395: if (stat_addr)
396: verify_area(stat_addr,4);
1.1 root 397: repeat:
1.1.1.2 root 398: flag=0;
1.1.1.4 root 399: for (p = current->p_cptr ; p ; p = p->p_osptr) {
1.1.1.2 root 400: if (pid>0) {
1.1.1.4 root 401: if (p->pid != pid)
1.1.1.2 root 402: continue;
403: } else if (!pid) {
1.1.1.4 root 404: if (p->pgrp != current->pgrp)
1.1.1.2 root 405: continue;
406: } else if (pid != -1) {
1.1.1.4 root 407: if (p->pgrp != -pid)
1.1.1.2 root 408: continue;
409: }
1.1.1.4 root 410: switch (p->state) {
1.1.1.2 root 411: case TASK_STOPPED:
1.1.1.8 ! root 412: if (!p->exit_code)
! 413: continue;
! 414: if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
1.1.1.2 root 415: continue;
1.1.1.5 root 416: if (stat_addr)
417: put_fs_long((p->exit_code << 8) | 0x7f,
418: stat_addr);
1.1.1.4 root 419: p->exit_code = 0;
420: return p->pid;
1.1.1.2 root 421: case TASK_ZOMBIE:
1.1.1.7 root 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;
1.1.1.4 root 426: flag = p->pid;
1.1.1.5 root 427: if (stat_addr)
428: put_fs_long(p->exit_code, stat_addr);
1.1.1.4 root 429: release(p);
430: #ifdef DEBUG_PROC_TREE
431: audit_ptree();
432: #endif
1.1.1.2 root 433: return flag;
434: default:
1.1 root 435: flag=1;
1.1.1.2 root 436: continue;
437: }
438: }
1.1 root 439: if (flag) {
440: if (options & WNOHANG)
441: return 0;
1.1.1.2 root 442: current->state=TASK_INTERRUPTIBLE;
1.1.1.4 root 443: oldblocked = current->blocked;
444: current->blocked &= ~(1<<(SIGCHLD-1));
1.1.1.2 root 445: schedule();
1.1.1.4 root 446: current->blocked = oldblocked;
447: if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
448: return -ERESTARTSYS;
1.1 root 449: else
1.1.1.4 root 450: goto repeat;
1.1 root 451: }
452: return -ECHILD;
453: }
454:
455:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.