|
|
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.5 root 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: /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
36: if ((sig >= SIGSTOP) && (sig <= SIGTTOU))
37: p->signal &= ~(1<<(SIGCONT-1));
38: /* Actually deliver the signal */
39: p->signal |= (1<<(sig-1));
40: if (p->flags & PF_PTRACED) {
41: /* save the signal number for wait. */
42: p->exit_code = sig;
43:
44: /* we have to make sure the parent is awake. */
45: if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
46: p->p_pptr->state = TASK_RUNNING;
47:
48: /* we have to make sure that the process stops. */
49: if (p->state == TASK_INTERRUPTIBLE || p->state == TASK_RUNNING)
50: p->state = TASK_STOPPED;
51: }
52: return 0;
53: }
54:
1.1 root 55: void release(struct task_struct * p)
56: {
57: int i;
58:
59: if (!p)
60: return;
1.1.1.4 root 61: if (p == current) {
62: printk("task releasing itself\n\r");
63: return;
64: }
1.1 root 65: for (i=1 ; i<NR_TASKS ; i++)
1.1.1.7 ! root 66: if (task[i] == p) {
! 67: task[i] = NULL;
1.1.1.4 root 68: /* Update links */
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;
1.1.1.7 ! root 75: free_page((long) p);
1.1 root 76: return;
77: }
78: panic("trying to release non-existent task");
79: }
80:
1.1.1.4 root 81: #ifdef DEBUG_PROC_TREE
82: /*
83: * Check to see if a task_struct pointer is present in the task[] array
84: * Return 0 if found, and 1 if not found.
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: * This routine scans the pid tree and make sure the rep invarient still
100: * holds. Used for debugging only, since it's very slow....
101: *
102: * It looks a lot scarier than it really is.... we're doing �nothing more
103: * than verifying the doubly-linked list found�in p_ysptr and p_osptr,
104: * and checking it corresponds with the process tree defined by p_cptr and
105: * p_pptr;
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 /* DEBUG_PROC_TREE */
169:
170: int session_of_pgrp(int pgrp)
1.1.1.2 root 171: {
1.1.1.4 root 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:
1.1.1.5 root 186: if (sig<0 || sig>32 || pgrp<=0)
1.1.1.4 root 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:
1.1.1.5 root 202: if (sig<0 || sig>32)
1.1.1.4 root 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);
1.1.1.2 root 208: }
209:
210: /*
1.1.1.4 root 211: * POSIX specifies that kill(-1,sig) is unspecified, but what we have
212: * is probably wrong. Should make it like BSD or SYSV.
1.1.1.2 root 213: */
214: int sys_kill(int pid,int sig)
1.1 root 215: {
216: struct task_struct **p = NR_TASKS + task;
1.1.1.7 ! root 217: int err, retval = 0, count = 0;
1.1 root 218:
1.1.1.4 root 219: if (!pid)
1.1.1.7 ! root 220: return(kill_pg(current->pgrp,sig,0));
1.1.1.4 root 221: if (pid == -1) {
222: while (--p > &FIRST_TASK)
1.1.1.7 ! root 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);
1.1.1.4 root 229: }
230: if (pid < 0)
231: return(kill_pg(-pid,sig,0));
232: /* Normal kill */
233: return(kill_proc(pid,sig,0));
1.1 root 234: }
235:
1.1.1.4 root 236: /*
237: * Determine if a process group is "orphaned", according to the POSIX
238: * definition in 2.2.2.52. Orphaned process groups are not to be affected
239: * by terminal-generated stop signals. Newly orphaned process groups are
240: * to receive a SIGHUP and a SIGCONT.
241: *
242: * "I ask you, have you ever known what it is to be an orphan?"
243: */
244: int is_orphaned_pgrp(int pgrp)
1.1 root 245: {
1.1.1.4 root 246: struct task_struct **p;
1.1.1.2 root 247:
1.1.1.4 root 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); /* (sighing) "Often!" */
1.1 root 259: }
260:
1.1.1.4 root 261: static int has_stopped_jobs(int pgrp)
1.1 root 262: {
1.1.1.4 root 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;
1.1 root 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);
1.1.1.4 root 285: current->pwd = NULL;
1.1 root 286: iput(current->root);
1.1.1.4 root 287: current->root = NULL;
1.1.1.3 root 288: iput(current->executable);
1.1.1.4 root 289: current->executable = NULL;
290: iput(current->library);
291: current->library = NULL;
1.1.1.2 root 292: current->state = TASK_ZOMBIE;
293: current->exit_code = code;
1.1.1.7 ! root 294: current->rss = 0;
1.1.1.4 root 295: /*
296: * Check to see if any process groups have become orphaned
297: * as a result of our exiting, and if they have any stopped
298: * jobs, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
299: *
300: * Case i: Our father is in a different pgrp than we are
301: * and we were the only connection outside, so our pgrp
302: * is about to become orphaned.
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: /* Let father know we died */
1.1.1.5 root 312: send_sig (SIGCHLD, current->p_pptr, 1);
1.1.1.4 root 313:
314: /*
315: * This loop does two things:
316: *
317: * A. Make init inherit all the child processes
318: * B. Check to see if any process groups have become orphaned
319: * as a result of our exiting, and if they have any stopped
320: * jons, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
321: */
1.1.1.7 ! root 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: * process group orphan check
! 334: * Case ii: Our child is in a different pgrp
! 335: * than we are, and it was the only connection
! 336: * outside, so the child pgrp is now orphaned.
! 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);
1.1.1.4 root 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);
1.1.1.6 root 352: if (tty->pgrp > 0)
1.1.1.4 root 353: kill_pg(tty->pgrp, SIGHUP, 1);
1.1.1.6 root 354: tty->pgrp = -1;
1.1.1.4 root 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
1.1 root 366: schedule();
367: }
368:
369: int sys_exit(int error_code)
370: {
1.1.1.4 root 371: do_exit((error_code&0xff)<<8);
1.1 root 372: }
373:
1.1.1.2 root 374: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
1.1 root 375: {
1.1.1.4 root 376: int flag;
377: struct task_struct *p;
378: unsigned long oldblocked;
1.1 root 379:
1.1.1.5 root 380: if (stat_addr)
381: verify_area(stat_addr,4);
1.1 root 382: repeat:
1.1.1.2 root 383: flag=0;
1.1.1.4 root 384: for (p = current->p_cptr ; p ; p = p->p_osptr) {
1.1.1.2 root 385: if (pid>0) {
1.1.1.4 root 386: if (p->pid != pid)
1.1.1.2 root 387: continue;
388: } else if (!pid) {
1.1.1.4 root 389: if (p->pgrp != current->pgrp)
1.1.1.2 root 390: continue;
391: } else if (pid != -1) {
1.1.1.4 root 392: if (p->pgrp != -pid)
1.1.1.2 root 393: continue;
394: }
1.1.1.4 root 395: switch (p->state) {
1.1.1.2 root 396: case TASK_STOPPED:
1.1.1.4 root 397: if (!(options & WUNTRACED) ||
398: !p->exit_code)
1.1.1.2 root 399: continue;
1.1.1.5 root 400: if (stat_addr)
401: put_fs_long((p->exit_code << 8) | 0x7f,
402: stat_addr);
1.1.1.4 root 403: p->exit_code = 0;
404: return p->pid;
1.1.1.2 root 405: case TASK_ZOMBIE:
1.1.1.7 ! root 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;
1.1.1.4 root 410: flag = p->pid;
1.1.1.5 root 411: if (stat_addr)
412: put_fs_long(p->exit_code, stat_addr);
1.1.1.4 root 413: release(p);
414: #ifdef DEBUG_PROC_TREE
415: audit_ptree();
416: #endif
1.1.1.2 root 417: return flag;
418: default:
1.1 root 419: flag=1;
1.1.1.2 root 420: continue;
421: }
422: }
1.1 root 423: if (flag) {
424: if (options & WNOHANG)
425: return 0;
1.1.1.2 root 426: current->state=TASK_INTERRUPTIBLE;
1.1.1.4 root 427: oldblocked = current->blocked;
428: current->blocked &= ~(1<<(SIGCHLD-1));
1.1.1.2 root 429: schedule();
1.1.1.4 root 430: current->blocked = oldblocked;
431: if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
432: return -ERESTARTSYS;
1.1 root 433: else
1.1.1.4 root 434: goto repeat;
1.1 root 435: }
436: return -ECHILD;
437: }
438:
439:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.