|
|
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: if (p == current)
53: schedule();
54: }
55: return 0;
56: }
57:
1.1 root 58: void release(struct task_struct * p)
59: {
60: int i;
61:
62: if (!p)
63: return;
1.1.1.4 root 64: if (p == current) {
65: printk("task releasing itself\n\r");
66: return;
67: }
1.1 root 68: for (i=1 ; i<NR_TASKS ; i++)
69: if (task[i]==p) {
70: task[i]=NULL;
1.1.1.4 root 71: /* Update links */
72: if (p->p_osptr)
73: p->p_osptr->p_ysptr = p->p_ysptr;
74: if (p->p_ysptr)
75: p->p_ysptr->p_osptr = p->p_osptr;
76: else
77: p->p_pptr->p_cptr = p->p_osptr;
1.1 root 78: free_page((long)p);
79: schedule();
80: return;
81: }
82: panic("trying to release non-existent task");
83: }
84:
1.1.1.4 root 85: #ifdef DEBUG_PROC_TREE
86: /*
87: * Check to see if a task_struct pointer is present in the task[] array
88: * Return 0 if found, and 1 if not found.
89: */
90: int bad_task_ptr(struct task_struct *p)
91: {
92: int i;
93:
94: if (!p)
95: return 0;
96: for (i=0 ; i<NR_TASKS ; i++)
97: if (task[i] == p)
98: return 0;
99: return 1;
100: }
101:
102: /*
103: * This routine scans the pid tree and make sure the rep invarient still
104: * holds. Used for debugging only, since it's very slow....
105: *
106: * It looks a lot scarier than it really is.... we're doing �nothing more
107: * than verifying the doubly-linked list found�in p_ysptr and p_osptr,
108: * and checking it corresponds with the process tree defined by p_cptr and
109: * p_pptr;
110: */
111: void audit_ptree()
112: {
113: int i;
114:
115: for (i=1 ; i<NR_TASKS ; i++) {
116: if (!task[i])
117: continue;
118: if (bad_task_ptr(task[i]->p_pptr))
119: printk("Warning, pid %d's parent link is bad\n",
120: task[i]->pid);
121: if (bad_task_ptr(task[i]->p_cptr))
122: printk("Warning, pid %d's child link is bad\n",
123: task[i]->pid);
124: if (bad_task_ptr(task[i]->p_ysptr))
125: printk("Warning, pid %d's ys link is bad\n",
126: task[i]->pid);
127: if (bad_task_ptr(task[i]->p_osptr))
128: printk("Warning, pid %d's os link is bad\n",
129: task[i]->pid);
130: if (task[i]->p_pptr == task[i])
131: printk("Warning, pid %d parent link points to self\n");
132: if (task[i]->p_cptr == task[i])
133: printk("Warning, pid %d child link points to self\n");
134: if (task[i]->p_ysptr == task[i])
135: printk("Warning, pid %d ys link points to self\n");
136: if (task[i]->p_osptr == task[i])
137: printk("Warning, pid %d os link points to self\n");
138: if (task[i]->p_osptr) {
139: if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
140: printk(
141: "Warning, pid %d older sibling %d parent is %d\n",
142: task[i]->pid, task[i]->p_osptr->pid,
143: task[i]->p_osptr->p_pptr->pid);
144: if (task[i]->p_osptr->p_ysptr != task[i])
145: printk(
146: "Warning, pid %d older sibling %d has mismatched ys link\n",
147: task[i]->pid, task[i]->p_osptr->pid);
148: }
149: if (task[i]->p_ysptr) {
150: if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
151: printk(
152: "Warning, pid %d younger sibling %d parent is %d\n",
153: task[i]->pid, task[i]->p_osptr->pid,
154: task[i]->p_osptr->p_pptr->pid);
155: if (task[i]->p_ysptr->p_osptr != task[i])
156: printk(
157: "Warning, pid %d younger sibling %d has mismatched os link\n",
158: task[i]->pid, task[i]->p_ysptr->pid);
159: }
160: if (task[i]->p_cptr) {
161: if (task[i]->p_cptr->p_pptr != task[i])
162: printk(
163: "Warning, pid %d youngest child %d has mismatched parent link\n",
164: task[i]->pid, task[i]->p_cptr->pid);
165: if (task[i]->p_cptr->p_ysptr)
166: printk(
167: "Warning, pid %d youngest child %d has non-NULL ys link\n",
168: task[i]->pid, task[i]->p_cptr->pid);
169: }
170: }
171: }
172: #endif /* DEBUG_PROC_TREE */
173:
174: int session_of_pgrp(int pgrp)
1.1.1.2 root 175: {
1.1.1.4 root 176: struct task_struct **p;
177:
178: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
179: if ((*p)->pgrp == pgrp)
180: return((*p)->session);
181: return -1;
182: }
183:
184: int kill_pg(int pgrp, int sig, int priv)
185: {
186: struct task_struct **p;
187: int err,retval = -ESRCH;
188: int found = 0;
189:
1.1.1.5 root 190: if (sig<0 || sig>32 || pgrp<=0)
1.1.1.4 root 191: return -EINVAL;
192: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
193: if ((*p)->pgrp == pgrp) {
194: if (sig && (err = send_sig(sig,*p,priv)))
195: retval = err;
196: else
197: found++;
198: }
199: return(found ? 0 : retval);
200: }
201:
202: int kill_proc(int pid, int sig, int priv)
203: {
204: struct task_struct **p;
205:
1.1.1.5 root 206: if (sig<0 || sig>32)
1.1.1.4 root 207: return -EINVAL;
208: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
209: if ((*p)->pid == pid)
210: return(sig ? send_sig(sig,*p,priv) : 0);
211: return(-ESRCH);
1.1.1.2 root 212: }
213:
214: /*
1.1.1.4 root 215: * POSIX specifies that kill(-1,sig) is unspecified, but what we have
216: * is probably wrong. Should make it like BSD or SYSV.
1.1.1.2 root 217: */
218: int sys_kill(int pid,int sig)
1.1 root 219: {
220: struct task_struct **p = NR_TASKS + task;
1.1.1.2 root 221: int err, retval = 0;
1.1 root 222:
1.1.1.4 root 223: if (!pid)
224: return(kill_pg(current->pid,sig,0));
225: if (pid == -1) {
226: while (--p > &FIRST_TASK)
1.1.1.2 root 227: if (err = send_sig(sig,*p,0))
228: retval = err;
1.1.1.4 root 229: return(retval);
230: }
231: if (pid < 0)
232: return(kill_pg(-pid,sig,0));
233: /* Normal kill */
234: return(kill_proc(pid,sig,0));
1.1 root 235: }
236:
1.1.1.4 root 237: /*
238: * Determine if a process group is "orphaned", according to the POSIX
239: * definition in 2.2.2.52. Orphaned process groups are not to be affected
240: * by terminal-generated stop signals. Newly orphaned process groups are
241: * to receive a SIGHUP and a SIGCONT.
242: *
243: * "I ask you, have you ever known what it is to be an orphan?"
244: */
245: int is_orphaned_pgrp(int pgrp)
1.1 root 246: {
1.1.1.4 root 247: struct task_struct **p;
1.1.1.2 root 248:
1.1.1.4 root 249: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
250: if (!(*p) ||
251: ((*p)->pgrp != pgrp) ||
252: ((*p)->state == TASK_ZOMBIE) ||
253: ((*p)->p_pptr->pid == 1))
254: continue;
255: if (((*p)->p_pptr->pgrp != pgrp) &&
256: ((*p)->p_pptr->session == (*p)->session))
257: return 0;
258: }
259: return(1); /* (sighing) "Often!" */
1.1 root 260: }
261:
1.1.1.4 root 262: static int has_stopped_jobs(int pgrp)
1.1 root 263: {
1.1.1.4 root 264: struct task_struct ** p;
265:
266: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
267: if ((*p)->pgrp != pgrp)
268: continue;
269: if ((*p)->state == TASK_STOPPED)
270: return(1);
271: }
272: return(0);
273: }
274:
275: volatile void do_exit(long code)
276: {
277: struct task_struct *p;
1.1 root 278: int i;
279:
280: free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
281: free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
282: for (i=0 ; i<NR_OPEN ; i++)
283: if (current->filp[i])
284: sys_close(i);
285: iput(current->pwd);
1.1.1.4 root 286: current->pwd = NULL;
1.1 root 287: iput(current->root);
1.1.1.4 root 288: current->root = NULL;
1.1.1.3 root 289: iput(current->executable);
1.1.1.4 root 290: current->executable = NULL;
291: iput(current->library);
292: current->library = NULL;
1.1.1.2 root 293: current->state = TASK_ZOMBIE;
294: current->exit_code = code;
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: */
322: if (p = current->p_cptr) {
323: while (1) {
1.1.1.5 root 324: p->flags &= ~PF_PTRACED;
1.1.1.4 root 325: p->p_pptr = task[1];
326: if (p->state == TASK_ZOMBIE)
327: task[1]->signal |= (1<<(SIGCHLD-1));
328: /*
329: * process group orphan check
330: * Case ii: Our child is in a different pgrp
331: * than we are, and it was the only connection
332: * outside, so the child pgrp is now orphaned.
333: */
334: if ((p->pgrp != current->pgrp) &&
335: (p->session == current->session) &&
336: is_orphaned_pgrp(p->pgrp) &&
337: has_stopped_jobs(p->pgrp)) {
338: kill_pg(p->pgrp,SIGHUP,1);
339: kill_pg(p->pgrp,SIGCONT,1);
340: }
341: if (p->p_osptr) {
342: p = p->p_osptr;
343: continue;
344: }
345: /*
346: * This is it; link everything into init's children
347: * and leave
348: */
349: p->p_osptr = task[1]->p_cptr;
350: task[1]->p_cptr->p_ysptr = p;
351: task[1]->p_cptr = current->p_cptr;
352: current->p_cptr = 0;
353: break;
354: }
355: }
356: if (current->leader) {
357: struct task_struct **p;
358: struct tty_struct *tty;
359:
360: if (current->tty >= 0) {
361: tty = TTY_TABLE(current->tty);
1.1.1.6 ! root 362: if (tty->pgrp > 0)
1.1.1.4 root 363: kill_pg(tty->pgrp, SIGHUP, 1);
1.1.1.6 ! root 364: tty->pgrp = -1;
1.1.1.4 root 365: tty->session = 0;
366: }
367: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
368: if ((*p)->session == current->session)
369: (*p)->tty = -1;
370: }
371: if (last_task_used_math == current)
372: last_task_used_math = NULL;
373: #ifdef DEBUG_PROC_TREE
374: audit_ptree();
375: #endif
1.1 root 376: schedule();
377: }
378:
379: int sys_exit(int error_code)
380: {
1.1.1.4 root 381: do_exit((error_code&0xff)<<8);
1.1 root 382: }
383:
1.1.1.2 root 384: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
1.1 root 385: {
1.1.1.4 root 386: int flag;
387: struct task_struct *p;
388: unsigned long oldblocked;
1.1 root 389:
1.1.1.5 root 390: if (stat_addr)
391: verify_area(stat_addr,4);
1.1 root 392: repeat:
1.1.1.2 root 393: flag=0;
1.1.1.4 root 394: for (p = current->p_cptr ; p ; p = p->p_osptr) {
1.1.1.2 root 395: if (pid>0) {
1.1.1.4 root 396: if (p->pid != pid)
1.1.1.2 root 397: continue;
398: } else if (!pid) {
1.1.1.4 root 399: if (p->pgrp != current->pgrp)
1.1.1.2 root 400: continue;
401: } else if (pid != -1) {
1.1.1.4 root 402: if (p->pgrp != -pid)
1.1.1.2 root 403: continue;
404: }
1.1.1.4 root 405: switch (p->state) {
1.1.1.2 root 406: case TASK_STOPPED:
1.1.1.4 root 407: if (!(options & WUNTRACED) ||
408: !p->exit_code)
1.1.1.2 root 409: continue;
1.1.1.5 root 410: if (stat_addr)
411: put_fs_long((p->exit_code << 8) | 0x7f,
412: stat_addr);
1.1.1.4 root 413: p->exit_code = 0;
414: return p->pid;
1.1.1.2 root 415: case TASK_ZOMBIE:
1.1.1.4 root 416: current->cutime += p->utime;
417: current->cstime += p->stime;
418: flag = p->pid;
1.1.1.5 root 419: if (stat_addr)
420: put_fs_long(p->exit_code, stat_addr);
1.1.1.4 root 421: release(p);
422: #ifdef DEBUG_PROC_TREE
423: audit_ptree();
424: #endif
1.1.1.2 root 425: return flag;
426: default:
1.1 root 427: flag=1;
1.1.1.2 root 428: continue;
429: }
430: }
1.1 root 431: if (flag) {
432: if (options & WNOHANG)
433: return 0;
1.1.1.2 root 434: current->state=TASK_INTERRUPTIBLE;
1.1.1.4 root 435: oldblocked = current->blocked;
436: current->blocked &= ~(1<<(SIGCHLD-1));
1.1.1.2 root 437: schedule();
1.1.1.4 root 438: current->blocked = oldblocked;
439: if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
440: return -ERESTARTSYS;
1.1 root 441: else
1.1.1.4 root 442: goto repeat;
1.1 root 443: }
444: return -ECHILD;
445: }
446:
447:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.