File:  [Early Linux] / linux / kernel / exit.c
Revision 1.1.1.12 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:15:09 2018 UTC (2 years, 2 months ago) by root
Branches: linus, MAIN
CVS tags: linux098, HEAD
linux 0.98

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

unix.superglobalmegacorp.com