kernel/exit.c
22927 /*
22928 * linux/kernel/exit.c
22929 *
22930 * Copyright (C) 1991, 1992 Linus Torvalds
22931 */
22932
22933 #include <linux/config.h>
22934 #include <linux/malloc.h>
22935 #include <linux/interrupt.h>
22936 #include <linux/smp_lock.h>
22937 #include <linux/module.h>
22938 #ifdef CONFIG_BSD_PROCESS_ACCT
22939 #include <linux/acct.h>
22940 #endif
22941
22942 #include <asm/uaccess.h>
22943 #include <asm/pgtable.h>
22944 #include <asm/mmu_context.h>
22945
22946 extern void sem_exit (void);
22947 extern struct task_struct *child_reaper;
22948
22949 int getrusage(struct task_struct *, int, struct rusage*);
22950
22951 static void release(struct task_struct * p)
22952 {
22953 if (p != current) {
22954 #ifdef __SMP__
22955 /* Wait to make sure the process isn't active on any
22956 * other CPU */
22957 for (;;) {
22958 int has_cpu;
22959 spin_lock(&scheduler_lock);
22960 has_cpu = p->has_cpu;
22961 spin_unlock(&scheduler_lock);
22962 if (!has_cpu)
22963 break;
22964 do {
22965 barrier();
22966 } while (p->has_cpu);
22967 }
22968 #endif
22969 free_uid(p);
22970 nr_tasks--;
22971 add_free_taskslot(p->tarray_ptr);
22972
22973 write_lock_irq(&tasklist_lock);
22974 unhash_pid(p);
22975 REMOVE_LINKS(p);
22976 write_unlock_irq(&tasklist_lock);
22977
22978 release_thread(p);
22979 current->cmin_flt += p->min_flt + p->cmin_flt;
22980 current->cmaj_flt += p->maj_flt + p->cmaj_flt;
22981 current->cnswap += p->nswap + p->cnswap;
22982 free_task_struct(p);
22983 } else {
22984 printk("task releasing itself\n");
22985 }
22986 }
22987
22988 /* This checks not only the pgrp, but falls back on the
22989 * pid if no satisfactory pgrp is found. I dunno - gdb
22990 * doesn't work correctly without this... */
22991 int session_of_pgrp(int pgrp)
22992 {
22993 struct task_struct *p;
22994 int fallback;
22995
22996 fallback = -1;
22997 read_lock(&tasklist_lock);
22998 for_each_task(p) {
22999 if (p->session <= 0)
23000 continue;
23001 if (p->pgrp == pgrp) {
23002 fallback = p->session;
23003 break;
23004 }
23005 if (p->pid == pgrp)
23006 fallback = p->session;
23007 }
23008 read_unlock(&tasklist_lock);
23009 return fallback;
23010 }
23011
23012 /* Determine if a process group is "orphaned", according
23013 * to the POSIX definition in 2.2.2.52. Orphaned process
23014 * groups are not to be affected by terminal-generated
23015 * stop signals. Newly orphaned process groups are to
23016 * receive a SIGHUP and a SIGCONT.
23017 *
23018 * "I ask you, have you ever known what it is to be an
23019 * orphan?" */
23020 static int will_become_orphaned_pgrp(int pgrp,
23021 struct task_struct * ignored_task)
23022 {
23023 struct task_struct *p;
23024
23025 read_lock(&tasklist_lock);
23026 for_each_task(p) {
23027 if ((p == ignored_task) || (p->pgrp != pgrp) ||
23028 (p->state == TASK_ZOMBIE) ||
23029 (p->p_pptr->pid == 1))
23030 continue;
23031 if ((p->p_pptr->pgrp != pgrp) &&
23032 (p->p_pptr->session == p->session)) {
23033 read_unlock(&tasklist_lock);
23034 return 0;
23035 }
23036 }
23037 read_unlock(&tasklist_lock);
23038 return 1; /* (sighing) "Often!" */
23039 }
23040
23041 int is_orphaned_pgrp(int pgrp)
23042 {
23043 return will_become_orphaned_pgrp(pgrp, 0);
23044 }
23045
23046 static inline int has_stopped_jobs(int pgrp)
23047 {
23048 int retval = 0;
23049 struct task_struct * p;
23050
23051 read_lock(&tasklist_lock);
23052 for_each_task(p) {
23053 if (p->pgrp != pgrp)
23054 continue;
23055 if (p->state != TASK_STOPPED)
23056 continue;
23057 retval = 1;
23058 break;
23059 }
23060 read_unlock(&tasklist_lock);
23061 return retval;
23062 }
23063
23064 static inline void forget_original_parent(
23065 struct task_struct * father)
23066 {
23067 struct task_struct * p;
23068
23069 read_lock(&tasklist_lock);
23070 for_each_task(p) {
23071 if (p->p_opptr == father) {
23072 p->exit_signal = SIGCHLD;
23073 p->p_opptr = child_reaper; /* init */
23074 if (p->pdeath_signal)
23075 send_sig(p->pdeath_signal, p, 0);
23076 }
23077 }
23078 read_unlock(&tasklist_lock);
23079 }
23080
23081 static inline void close_files(
23082 struct files_struct * files)
23083 {
23084 int i, j;
23085
23086 j = 0;
23087 for (;;) {
23088 unsigned long set = files->open_fds.fds_bits[j];
23089 i = j * __NFDBITS;
23090 j++;
23091 if (i >= files->max_fds)
23092 break;
23093 while (set) {
23094 if (set & 1) {
23095 struct file * file = files->fd[i];
23096 if (file) {
23097 files->fd[i] = NULL;
23098 filp_close(file, files);
23099 }
23100 }
23101 i++;
23102 set >>= 1;
23103 }
23104 }
23105 }
23106
23107 extern kmem_cache_t *files_cachep;
23108
23109 static inline void __exit_files(struct task_struct *tsk)
23110 {
23111 struct files_struct * files = tsk->files;
23112
23113 if (files) {
23114 tsk->files = NULL;
23115 if (atomic_dec_and_test(&files->count)) {
23116 close_files(files);
23117 /* Free the fd array as appropriate ... */
23118 if (NR_OPEN * sizeof(struct file *) == PAGE_SIZE)
23119 free_page((unsigned long) files->fd);
23120 else
23121 kfree(files->fd);
23122 kmem_cache_free(files_cachep, files);
23123 }
23124 }
23125 }
23126
23127 void exit_files(struct task_struct *tsk)
23128 {
23129 __exit_files(tsk);
23130 }
23131
23132 static inline void __exit_fs(struct task_struct *tsk)
23133 {
23134 struct fs_struct * fs = tsk->fs;
23135
23136 if (fs) {
23137 tsk->fs = NULL;
23138 if (atomic_dec_and_test(&fs->count)) {
23139 dput(fs->root);
23140 dput(fs->pwd);
23141 kfree(fs);
23142 }
23143 }
23144 }
23145
23146 void exit_fs(struct task_struct *tsk)
23147 {
23148 __exit_fs(tsk);
23149 }
23150
23151 static inline void __exit_sighand(
23152 struct task_struct *tsk)
23153 {
23154 struct signal_struct * sig = tsk->sig;
23155
23156 if (sig) {
23157 unsigned long flags;
23158
23159 spin_lock_irqsave(&tsk->sigmask_lock, flags);
23160 tsk->sig = NULL;
23161 spin_unlock_irqrestore(&tsk->sigmask_lock, flags);
23162 if (atomic_dec_and_test(&sig->count))
23163 kfree(sig);
23164 }
23165
23166 flush_signals(tsk);
23167 }
23168
23169 void exit_sighand(struct task_struct *tsk)
23170 {
23171 __exit_sighand(tsk);
23172 }
23173
23174 static inline void __exit_mm(struct task_struct * tsk)
23175 {
23176 struct mm_struct * mm = tsk->mm;
23177
23178 /* Set us up to use the kernel mm state */
23179 if (mm != &init_mm) {
23180 flush_cache_mm(mm);
23181 flush_tlb_mm(mm);
23182 destroy_context(mm);
23183 tsk->mm = &init_mm;
23184 tsk->swappable = 0;
23185 SET_PAGE_DIR(tsk, swapper_pg_dir);
23186 mm_release();
23187 mmput(mm);
23188 }
23189 }
23190
23191 void exit_mm(struct task_struct *tsk)
23192 {
23193 __exit_mm(tsk);
23194 }
23195
23196 /* Send signals to all our closest relatives so that they
23197 * know to properly mourn us.. */
23198 static void exit_notify(void)
23199 {
23200 struct task_struct * p;
23201
23202 forget_original_parent(current);
23203 /* Check to see if any process groups have become
23204 * orphaned as a result of our exiting, and if they
23205 * have any stopped jobs, send them a SIGHUP and then a
23206 * SIGCONT. (POSIX 3.2.2.2)
23207 *
23208 * Case i: Our father is in a different pgrp than we
23209 * are and we were the only connection outside, so our
23210 * pgrp is about to become orphaned. */
23211 if ((current->p_pptr->pgrp != current->pgrp) &&
23212 (current->p_pptr->session == current->session) &&
23213 will_become_orphaned_pgrp(current->pgrp, current)&&
23214 has_stopped_jobs(current->pgrp)) {
23215 kill_pg(current->pgrp,SIGHUP,1);
23216 kill_pg(current->pgrp,SIGCONT,1);
23217 }
23218
23219 /* Let father know we died */
23220 notify_parent(current, current->exit_signal);
23221
23222 /* This loop does two things:
23223 *
23224 * A. Make init inherit all the child processes
23225 * B. Check to see if any process groups have become
23226 * orphaned as a result of our exiting, and if they
23227 * have any stopped jobs, send them a SIGHUP and then a
23228 * SIGCONT. (POSIX 3.2.2.2) */
23229
23230 write_lock_irq(&tasklist_lock);
23231 while (current->p_cptr != NULL) {
23232 p = current->p_cptr;
23233 current->p_cptr = p->p_osptr;
23234 p->p_ysptr = NULL;
23235 p->flags &= ~(PF_PTRACED|PF_TRACESYS);
23236
23237 p->p_pptr = p->p_opptr;
23238 p->p_osptr = p->p_pptr->p_cptr;
23239 if (p->p_osptr)
23240 p->p_osptr->p_ysptr = p;
23241 p->p_pptr->p_cptr = p;
23242 if (p->state == TASK_ZOMBIE)
23243 notify_parent(p, p->exit_signal);
23244 /* process group orphan check
23245 * Case ii: Our child is in a different pgrp than we
23246 * are, and it was the only connection outside, so
23247 * the child pgrp is now orphaned. */
23248 if ((p->pgrp != current->pgrp) &&
23249 (p->session == current->session)) {
23250 int pgrp = p->pgrp;
23251
23252 write_unlock_irq(&tasklist_lock);
23253 if (is_orphaned_pgrp(pgrp) &&
23254 has_stopped_jobs(pgrp)) {
23255 kill_pg(pgrp,SIGHUP,1);
23256 kill_pg(pgrp,SIGCONT,1);
23257 }
23258 write_lock_irq(&tasklist_lock);
23259 }
23260 }
23261 write_unlock_irq(&tasklist_lock);
23262
23263 if (current->leader)
23264 disassociate_ctty(1);
23265 }
23266
23267 NORET_TYPE void do_exit(long code)
23268 {
23269 struct task_struct *tsk = current;
23270
23271 if (in_interrupt())
23272 printk("Aiee, killing interrupt handler\n");
23273 if (!tsk->pid)
23274 panic("Attempted to kill the idle task!");
23275 tsk->flags |= PF_EXITING;
23276 start_bh_atomic();
23277 del_timer(&tsk->real_timer);
23278 end_bh_atomic();
23279
23280 lock_kernel();
23281 fake_volatile:
23282 #ifdef CONFIG_BSD_PROCESS_ACCT
23283 acct_process(code);
23284 #endif
23285 sem_exit();
23286 __exit_mm(tsk);
23287 #if CONFIG_AP1000
23288 exit_msc(tsk);
23289 #endif
23290 __exit_files(tsk);
23291 __exit_fs(tsk);
23292 __exit_sighand(tsk);
23293 exit_thread();
23294 tsk->state = TASK_ZOMBIE;
23295 tsk->exit_code = code;
23296 exit_notify();
23297 #ifdef DEBUG_PROC_TREE
23298 audit_ptree();
23299 #endif
23300 if (tsk->exec_domain && tsk->exec_domain->module)
23301 __MOD_DEC_USE_COUNT(tsk->exec_domain->module);
23302 if (tsk->binfmt && tsk->binfmt->module)
23303 __MOD_DEC_USE_COUNT(tsk->binfmt->module);
23304 schedule();
23305 /* In order to get rid of the "volatile function does
23306 * return" message I did this little loop that confuses
23307 * gcc to think do_exit really is volatile. In fact it's
23308 * schedule() that is volatile in some circumstances:
23309 * when current->state = ZOMBIE, schedule() never
23310 * returns.
23311 *
23312 * In fact the natural way to do all this is to have the
23313 * label and the goto right after each other, but I put
23314 * the fake_volatile label at the start of the function
23315 * just in case something /really/ bad happens, and the
23316 * schedule returns. This way we can try again. I'm not
23317 * paranoid: it's just that everybody is out to get me.
23318 */
23319 goto fake_volatile;
23320 }
23321
23322 asmlinkage int sys_exit(int error_code)
23323 {
23324 do_exit((error_code&0xff)<<8);
23325 }
23326
23327 asmlinkage int sys_wait4(pid_t pid,
23328 unsigned int * stat_addr, int options,
23329 struct rusage * ru)
23330 {
23331 int flag, retval;
23332 struct wait_queue wait = { current, NULL };
23333 struct task_struct *p;
23334
23335 if (options & ~(WNOHANG|WUNTRACED|__WCLONE))
23336 return -EINVAL;
23337
23338 add_wait_queue(¤t->wait_chldexit,&wait);
23339 repeat:
23340 flag = 0;
23341 read_lock(&tasklist_lock);
23342 for (p = current->p_cptr ; p ; p = p->p_osptr) {
23343 if (pid>0) {
23344 if (p->pid != pid)
23345 continue;
23346 } else if (!pid) {
23347 if (p->pgrp != current->pgrp)
23348 continue;
23349 } else if (pid != -1) {
23350 if (p->pgrp != -pid)
23351 continue;
23352 }
23353 /* wait for cloned processes iff the __WCLONE flag is
23354 * set */
23355 if ((p->exit_signal != SIGCHLD) ^
23356 ((options & __WCLONE) != 0))
23357 continue;
23358 flag = 1;
23359 switch (p->state) {
23360 case TASK_STOPPED:
23361 if (!p->exit_code)
23362 continue;
23363 if (!(options & WUNTRACED) &&
23364 !(p->flags & PF_PTRACED))
23365 continue;
23366 read_unlock(&tasklist_lock);
23367 retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
23368 if (!retval && stat_addr)
23369 retval = put_user((p->exit_code << 8) | 0x7f,
23370 stat_addr);
23371 if (!retval) {
23372 p->exit_code = 0;
23373 retval = p->pid;
23374 }
23375 goto end_wait4;
23376 case TASK_ZOMBIE:
23377 current->times.tms_cutime += p->times.tms_utime +
23378 p->times.tms_cutime;
23379 current->times.tms_cstime += p->times.tms_stime +
23380 p->times.tms_cstime;
23381 read_unlock(&tasklist_lock);
23382 retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
23383 if (!retval && stat_addr)
23384 retval = put_user(p->exit_code, stat_addr);
23385 if (retval)
23386 goto end_wait4;
23387 retval = p->pid;
23388 if (p->p_opptr != p->p_pptr) {
23389 write_lock_irq(&tasklist_lock);
23390 REMOVE_LINKS(p);
23391 p->p_pptr = p->p_opptr;
23392 SET_LINKS(p);
23393 write_unlock_irq(&tasklist_lock);
23394 notify_parent(p, SIGCHLD);
23395 } else
23396 release(p);
23397 #ifdef DEBUG_PROC_TREE
23398 audit_ptree();
23399 #endif
23400 goto end_wait4;
23401 default:
23402 continue;
23403 }
23404 }
23405 read_unlock(&tasklist_lock);
23406 if (flag) {
23407 retval = 0;
23408 if (options & WNOHANG)
23409 goto end_wait4;
23410 retval = -ERESTARTSYS;
23411 if (signal_pending(current))
23412 goto end_wait4;
23413 current->state=TASK_INTERRUPTIBLE;
23414 schedule();
23415 goto repeat;
23416 }
23417 retval = -ECHILD;
23418 end_wait4:
23419 remove_wait_queue(¤t->wait_chldexit,&wait);
23420 return retval;
23421 }
23422
23423 #ifndef __alpha__
23424
23425 /* sys_waitpid() remains for compatibility. waitpid()
23426 * should be implemented by calling sys_wait4() from
23427 * libc.a. */
23428 asmlinkage int sys_waitpid(pid_t pid,
23429 unsigned int * stat_addr, int options)
23430 {
23431 return sys_wait4(pid, stat_addr, options, NULL);
23432 }
23433
23434 #endif
Сайт управляется системой
uCoz