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

    1: /*
    2:  *  linux/kernel/exit.c
    3:  *
    4:  *  (C) 1991  Linus Torvalds
    5:  */
    6: 
    7: #define DEBUG_PROC_TREE
    8: 
    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_pause(void);
   19: int sys_close(int fd);
   20: 
   21: void release(struct task_struct * p)
   22: {
   23: 	int i;
   24: 
   25: 	if (!p)
   26: 		return;
   27: 	if (p == current) {
   28: 		printk("task releasing itself\n\r");
   29: 		return;
   30: 	}
   31: 	for (i=1 ; i<NR_TASKS ; i++)
   32: 		if (task[i]==p) {
   33: 			task[i]=NULL;
   34: 			/* Update links */
   35: 			if (p->p_osptr)
   36: 				p->p_osptr->p_ysptr = p->p_ysptr;
   37: 			if (p->p_ysptr)
   38: 				p->p_ysptr->p_osptr = p->p_osptr;
   39: 			else
   40: 				p->p_pptr->p_cptr = p->p_osptr;
   41: 			free_page((long)p);
   42: 			schedule();
   43: 			return;
   44: 		}
   45: 	panic("trying to release non-existent task");
   46: }
   47: 
   48: #ifdef DEBUG_PROC_TREE
   49: /*
   50:  * Check to see if a task_struct pointer is present in the task[] array
   51:  * Return 0 if found, and 1 if not found.
   52:  */
   53: int bad_task_ptr(struct task_struct *p)
   54: {
   55: 	int 	i;
   56: 
   57: 	if (!p)
   58: 		return 0;
   59: 	for (i=0 ; i<NR_TASKS ; i++)
   60: 		if (task[i] == p)
   61: 			return 0;
   62: 	return 1;
   63: }
   64: 	
   65: /*
   66:  * This routine scans the pid tree and make sure the rep invarient still
   67:  * holds.  Used for debugging only, since it's very slow....
   68:  *
   69:  * It looks a lot scarier than it really is.... we're doing ænothing more
   70:  * than verifying the doubly-linked list foundæin p_ysptr and p_osptr, 
   71:  * and checking it corresponds with the process tree defined by p_cptr and 
   72:  * p_pptr;
   73:  */
   74: void audit_ptree()
   75: {
   76: 	int	i;
   77: 
   78: 	for (i=1 ; i<NR_TASKS ; i++) {
   79: 		if (!task[i])
   80: 			continue;
   81: 		if (bad_task_ptr(task[i]->p_pptr))
   82: 			printk("Warning, pid %d's parent link is bad\n",
   83: 				task[i]->pid);
   84: 		if (bad_task_ptr(task[i]->p_cptr))
   85: 			printk("Warning, pid %d's child link is bad\n",
   86: 				task[i]->pid);
   87: 		if (bad_task_ptr(task[i]->p_ysptr))
   88: 			printk("Warning, pid %d's ys link is bad\n",
   89: 				task[i]->pid);
   90: 		if (bad_task_ptr(task[i]->p_osptr))
   91: 			printk("Warning, pid %d's os link is bad\n",
   92: 				task[i]->pid);
   93: 		if (task[i]->p_pptr == task[i])
   94: 			printk("Warning, pid %d parent link points to self\n");
   95: 		if (task[i]->p_cptr == task[i])
   96: 			printk("Warning, pid %d child link points to self\n");
   97: 		if (task[i]->p_ysptr == task[i])
   98: 			printk("Warning, pid %d ys link points to self\n");
   99: 		if (task[i]->p_osptr == task[i])
  100: 			printk("Warning, pid %d os link points to self\n");
  101: 		if (task[i]->p_osptr) {
  102: 			if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
  103: 				printk(
  104: 			"Warning, pid %d older sibling %d parent is %d\n",
  105: 				task[i]->pid, task[i]->p_osptr->pid,
  106: 				task[i]->p_osptr->p_pptr->pid);
  107: 			if (task[i]->p_osptr->p_ysptr != task[i])
  108: 				printk(
  109: 		"Warning, pid %d older sibling %d has mismatched ys link\n",
  110: 				task[i]->pid, task[i]->p_osptr->pid);
  111: 		}
  112: 		if (task[i]->p_ysptr) {
  113: 			if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
  114: 				printk(
  115: 			"Warning, pid %d younger sibling %d parent is %d\n",
  116: 				task[i]->pid, task[i]->p_osptr->pid,
  117: 				task[i]->p_osptr->p_pptr->pid);
  118: 			if (task[i]->p_ysptr->p_osptr != task[i])
  119: 				printk(
  120: 		"Warning, pid %d younger sibling %d has mismatched os link\n",
  121: 				task[i]->pid, task[i]->p_ysptr->pid);
  122: 		}
  123: 		if (task[i]->p_cptr) {
  124: 			if (task[i]->p_cptr->p_pptr != task[i])
  125: 				printk(
  126: 			"Warning, pid %d youngest child %d has mismatched parent link\n",
  127: 				task[i]->pid, task[i]->p_cptr->pid);
  128: 			if (task[i]->p_cptr->p_ysptr)
  129: 				printk(
  130: 			"Warning, pid %d youngest child %d has non-NULL ys link\n",
  131: 				task[i]->pid, task[i]->p_cptr->pid);
  132: 		}
  133: 	}
  134: }
  135: #endif /* DEBUG_PROC_TREE */
  136: 
  137: static inline int send_sig(long sig,struct task_struct * p,int priv)
  138: {
  139: 	if (!p)
  140: 		return -EINVAL;
  141: 	if (!priv && (current->euid!=p->euid) && !suser())
  142: 		return -EPERM;
  143: 	if ((sig == SIGKILL) || (sig == SIGCONT)) {
  144: 		if (p->state == TASK_STOPPED)
  145: 			p->state = TASK_RUNNING;
  146: 		p->exit_code = 0;
  147: 		p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
  148: 				(1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
  149: 	} 
  150: 	/* If the signal will be ignored, don't even post it */
  151: 	if ((int) p->sigaction[sig-1].sa_handler == 1)
  152: 		return 0;
  153: 	/* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
  154: 	if ((sig >= SIGSTOP) && (sig <= SIGTTOU)) 
  155: 		p->signal &= ~(1<<(SIGCONT-1));
  156: 	/* Actually deliver the signal */
  157: 	p->signal |= (1<<(sig-1));
  158: 	return 0;
  159: }
  160: 
  161: int session_of_pgrp(int pgrp)
  162: {
  163: 	struct task_struct **p;
  164: 
  165:  	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
  166: 		if ((*p)->pgrp == pgrp)
  167: 			return((*p)->session);
  168: 	return -1;
  169: }
  170: 
  171: int kill_pg(int pgrp, int sig, int priv)
  172: {
  173: 	struct task_struct **p;
  174: 	int err,retval = -ESRCH;
  175: 	int found = 0;
  176: 
  177: 	if (sig<1 || sig>32 || pgrp<=0)
  178: 		return -EINVAL;
  179:  	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
  180: 		if ((*p)->pgrp == pgrp) {
  181: 			if (sig && (err = send_sig(sig,*p,priv)))
  182: 				retval = err;
  183: 			else
  184: 				found++;
  185: 		}
  186: 	return(found ? 0 : retval);
  187: }
  188: 
  189: int kill_proc(int pid, int sig, int priv)
  190: {
  191:  	struct task_struct **p;
  192: 
  193: 	if (sig<1 || sig>32)
  194: 		return -EINVAL;
  195: 	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
  196: 		if ((*p)->pid == pid)
  197: 			return(sig ? send_sig(sig,*p,priv) : 0);
  198: 	return(-ESRCH);
  199: }
  200: 
  201: /*
  202:  * POSIX specifies that kill(-1,sig) is unspecified, but what we have
  203:  * is probably wrong.  Should make it like BSD or SYSV.
  204:  */
  205: int sys_kill(int pid,int sig)
  206: {
  207: 	struct task_struct **p = NR_TASKS + task;
  208: 	int err, retval = 0;
  209: 
  210: 	if (!pid)
  211: 		return(kill_pg(current->pid,sig,0));
  212: 	if (pid == -1) {
  213: 		while (--p > &FIRST_TASK)
  214: 			if (err = send_sig(sig,*p,0))
  215: 				retval = err;
  216: 		return(retval);
  217: 	}
  218: 	if (pid < 0) 
  219: 		return(kill_pg(-pid,sig,0));
  220: 	/* Normal kill */
  221: 	return(kill_proc(pid,sig,0));
  222: }
  223: 
  224: /*
  225:  * Determine if a process group is "orphaned", according to the POSIX
  226:  * definition in 2.2.2.52.  Orphaned process groups are not to be affected
  227:  * by terminal-generated stop signals.  Newly orphaned process groups are 
  228:  * to receive a SIGHUP and a SIGCONT.
  229:  * 
  230:  * "I ask you, have you ever known what it is to be an orphan?"
  231:  */
  232: int is_orphaned_pgrp(int pgrp)
  233: {
  234: 	struct task_struct **p;
  235: 
  236: 	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
  237: 		if (!(*p) ||
  238: 		    ((*p)->pgrp != pgrp) || 
  239: 		    ((*p)->state == TASK_ZOMBIE) ||
  240: 		    ((*p)->p_pptr->pid == 1))
  241: 			continue;
  242: 		if (((*p)->p_pptr->pgrp != pgrp) &&
  243: 		    ((*p)->p_pptr->session == (*p)->session))
  244: 			return 0;
  245: 	}
  246: 	return(1);	/* (sighing) "Often!" */
  247: }
  248: 
  249: static int has_stopped_jobs(int pgrp)
  250: {
  251: 	struct task_struct ** p;
  252: 
  253: 	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
  254: 		if ((*p)->pgrp != pgrp)
  255: 			continue;
  256: 		if ((*p)->state == TASK_STOPPED)
  257: 			return(1);
  258: 	}
  259: 	return(0);
  260: }
  261: 
  262: volatile void do_exit(long code)
  263: {
  264: 	struct task_struct *p;
  265: 	int i;
  266: 
  267: 	free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
  268: 	free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
  269: 	for (i=0 ; i<NR_OPEN ; i++)
  270: 		if (current->filp[i])
  271: 			sys_close(i);
  272: 	iput(current->pwd);
  273: 	current->pwd = NULL;
  274: 	iput(current->root);
  275: 	current->root = NULL;
  276: 	iput(current->executable);
  277: 	current->executable = NULL;
  278: 	iput(current->library);
  279: 	current->library = NULL;
  280: 	current->state = TASK_ZOMBIE;
  281: 	current->exit_code = code;
  282: 	/* 
  283: 	 * Check to see if any process groups have become orphaned
  284: 	 * as a result of our exiting, and if they have any stopped
  285: 	 * jobs, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)
  286: 	 *
  287: 	 * Case i: Our father is in a different pgrp than we are
  288: 	 * and we were the only connection outside, so our pgrp
  289: 	 * is about to become orphaned.
  290:  	 */
  291: 	if ((current->p_pptr->pgrp != current->pgrp) &&
  292: 	    (current->p_pptr->session == current->session) &&
  293: 	    is_orphaned_pgrp(current->pgrp) &&
  294: 	    has_stopped_jobs(current->pgrp)) {
  295: 		kill_pg(current->pgrp,SIGHUP,1);
  296: 		kill_pg(current->pgrp,SIGCONT,1);
  297: 	}
  298: 	/* Let father know we died */
  299: 	current->p_pptr->signal |= (1<<(SIGCHLD-1));
  300: 	
  301: 	/*
  302: 	 * This loop does two things:
  303: 	 * 
  304:   	 * A.  Make init inherit all the child processes
  305: 	 * B.  Check to see if any process groups have become orphaned
  306: 	 *	as a result of our exiting, and if they have any stopped
  307: 	 *	jons, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)
  308: 	 */
  309: 	if (p = current->p_cptr) {
  310: 		while (1) {
  311: 			p->p_pptr = task[1];
  312: 			if (p->state == TASK_ZOMBIE)
  313: 				task[1]->signal |= (1<<(SIGCHLD-1));
  314: 			/*
  315: 			 * process group orphan check
  316: 			 * Case ii: Our child is in a different pgrp 
  317: 			 * than we are, and it was the only connection
  318: 			 * outside, so the child pgrp is now orphaned.
  319: 			 */
  320: 			if ((p->pgrp != current->pgrp) &&
  321: 			    (p->session == current->session) &&
  322: 			    is_orphaned_pgrp(p->pgrp) &&
  323: 			    has_stopped_jobs(p->pgrp)) {
  324: 				kill_pg(p->pgrp,SIGHUP,1);
  325: 				kill_pg(p->pgrp,SIGCONT,1);
  326: 			}
  327: 			if (p->p_osptr) {
  328: 				p = p->p_osptr;
  329: 				continue;
  330: 			}
  331: 			/*
  332: 			 * This is it; link everything into init's children 
  333: 			 * and leave 
  334: 			 */
  335: 			p->p_osptr = task[1]->p_cptr;
  336: 			task[1]->p_cptr->p_ysptr = p;
  337: 			task[1]->p_cptr = current->p_cptr;
  338: 			current->p_cptr = 0;
  339: 			break;
  340: 		}
  341: 	}
  342: 	if (current->leader) {
  343: 		struct task_struct **p;
  344: 		struct tty_struct *tty;
  345: 
  346: 		if (current->tty >= 0) {
  347: 			tty = TTY_TABLE(current->tty);
  348: 			if (tty->pgrp>0)
  349: 				kill_pg(tty->pgrp, SIGHUP, 1);
  350: 			tty->pgrp = 0;
  351: 			tty->session = 0;
  352: 		}
  353: 	 	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
  354: 			if ((*p)->session == current->session)
  355: 				(*p)->tty = -1;
  356: 	}
  357: 	if (last_task_used_math == current)
  358: 		last_task_used_math = NULL;
  359: #ifdef DEBUG_PROC_TREE
  360: 	audit_ptree();
  361: #endif
  362: 	schedule();
  363: }
  364: 
  365: int sys_exit(int error_code)
  366: {
  367: 	do_exit((error_code&0xff)<<8);
  368: }
  369: 
  370: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
  371: {
  372: 	int flag;
  373: 	struct task_struct *p;
  374: 	unsigned long oldblocked;
  375: 
  376: 	verify_area(stat_addr,4);
  377: repeat:
  378: 	flag=0;
  379: 	for (p = current->p_cptr ; p ; p = p->p_osptr) {
  380: 		if (pid>0) {
  381: 			if (p->pid != pid)
  382: 				continue;
  383: 		} else if (!pid) {
  384: 			if (p->pgrp != current->pgrp)
  385: 				continue;
  386: 		} else if (pid != -1) {
  387: 			if (p->pgrp != -pid)
  388: 				continue;
  389: 		}
  390: 		switch (p->state) {
  391: 			case TASK_STOPPED:
  392: 				if (!(options & WUNTRACED) || 
  393: 				    !p->exit_code)
  394: 					continue;
  395: 				put_fs_long((p->exit_code << 8) | 0x7f,
  396: 					stat_addr);
  397: 				p->exit_code = 0;
  398: 				return p->pid;
  399: 			case TASK_ZOMBIE:
  400: 				current->cutime += p->utime;
  401: 				current->cstime += p->stime;
  402: 				flag = p->pid;
  403: 				put_fs_long(p->exit_code, stat_addr);
  404: 				release(p);
  405: #ifdef DEBUG_PROC_TREE
  406: 				audit_ptree();
  407: #endif
  408: 				return flag;
  409: 			default:
  410: 				flag=1;
  411: 				continue;
  412: 		}
  413: 	}
  414: 	if (flag) {
  415: 		if (options & WNOHANG)
  416: 			return 0;
  417: 		current->state=TASK_INTERRUPTIBLE;
  418: 		oldblocked = current->blocked;
  419: 		current->blocked &= ~(1<<(SIGCHLD-1));
  420: 		schedule();
  421: 		current->blocked = oldblocked;
  422: 		if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
  423: 			return -ERESTARTSYS;
  424: 		else
  425: 			goto repeat;
  426: 	}
  427: 	return -ECHILD;
  428: }
  429: 
  430: 

unix.superglobalmegacorp.com