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