/* given a list of tasks, sample all the threads in 'em */ static void pet_sample_task_list( int taskc, task_array_t taskv ) { int i; for( i = 0; i < taskc; i++ ) { kern_return_t kr; task_t task = taskv[i]; /* FIXME: necessary? old code did this, our hacky * filtering code does, too */ if(!task) { continue; } /* try and stop any task other than the kernel task */ if( task != kernel_task ) { kr = task_suspend_internal( task ); /* try the next task */ if( kr != KERN_SUCCESS ) continue; } /* sample it */ pet_sample_task( task ); /* if it wasn't the kernel, resume it */ if( task != kernel_task ) (void) task_resume_internal(task); } }
/* Not called from probe context */ proc_t * sprlock(pid_t pid) { proc_t* p; if ((p = proc_find(pid)) == PROC_NULL) { return PROC_NULL; } task_suspend_internal(p->task); dtrace_sprlock(p); proc_lock(p); return p; }
static void proc_shutdown(void) { vfs_context_t ctx = vfs_context_current(); struct proc *p, *self; int delayterm = 0; struct sd_filterargs sfargs; struct sd_iterargs sdargs; int error = 0; struct timespec ts; /* * Kill as many procs as we can. (Except ourself...) */ self = (struct proc *)current_proc(); /* * Signal the init with SIGTERM so that he does not launch * new processes */ p = proc_find(1); if (p && p != self) { psignal(p, SIGTERM); } proc_rele(p); printf("Killing all processes "); sigterm_loop: /* * send SIGTERM to those procs interested in catching one */ sfargs.delayterm = delayterm; sfargs.shutdownstate = 0; sdargs.signo = SIGTERM; sdargs.setsdstate = 1; sdargs.countproc = 1; sdargs.activecount = 0; error = 0; /* post a SIGTERM to all that catch SIGTERM and not marked for delay */ proc_rebootscan(sd_callback1, (void *)&sdargs, sd_filt1, (void *)&sfargs); if (sdargs.activecount != 0 && proc_shutdown_exitcount!= 0) { proc_list_lock(); if (proc_shutdown_exitcount != 0) { /* * now wait for up to 30 seconds to allow those procs catching SIGTERM * to digest it * as soon as these procs have exited, we'll continue on to the next step */ ts.tv_sec = 30; ts.tv_nsec = 0; error = msleep(&proc_shutdown_exitcount, proc_list_mlock, PWAIT, "shutdownwait", &ts); if (error != 0) { for (p = allproc.lh_first; p; p = p->p_list.le_next) { if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) p->p_listflag &= ~P_LIST_EXITCOUNT; } for (p = zombproc.lh_first; p; p = p->p_list.le_next) { if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) p->p_listflag &= ~P_LIST_EXITCOUNT; } } } proc_list_unlock(); } if (error == ETIMEDOUT) { /* * log the names of the unresponsive tasks */ proc_list_lock(); for (p = allproc.lh_first; p; p = p->p_list.le_next) { if (p->p_shutdownstate == 1) { printf("%s[%d]: didn't act on SIGTERM\n", p->p_comm, p->p_pid); sd_log(ctx, "%s[%d]: didn't act on SIGTERM\n", p->p_comm, p->p_pid); } } proc_list_unlock(); delay_for_interval(1000 * 5, 1000 * 1000); } /* * send a SIGKILL to all the procs still hanging around */ sfargs.delayterm = delayterm; sfargs.shutdownstate = 2; sdargs.signo = SIGKILL; sdargs.setsdstate = 2; sdargs.countproc = 1; sdargs.activecount = 0; /* post a SIGKILL to all that catch SIGTERM and not marked for delay */ proc_rebootscan(sd_callback2, (void *)&sdargs, sd_filt2, (void *)&sfargs); if (sdargs.activecount != 0 && proc_shutdown_exitcount!= 0) { proc_list_lock(); if (proc_shutdown_exitcount != 0) { /* * wait for up to 60 seconds to allow these procs to exit normally * * History: The delay interval was changed from 100 to 200 * for NFS requests in particular. */ ts.tv_sec = 60; ts.tv_nsec = 0; error = msleep(&proc_shutdown_exitcount, proc_list_mlock, PWAIT, "shutdownwait", &ts); if (error != 0) { for (p = allproc.lh_first; p; p = p->p_list.le_next) { if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) p->p_listflag &= ~P_LIST_EXITCOUNT; } for (p = zombproc.lh_first; p; p = p->p_list.le_next) { if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) p->p_listflag &= ~P_LIST_EXITCOUNT; } } } proc_list_unlock(); } /* * if we still have procs that haven't exited, then brute force 'em */ sfargs.delayterm = delayterm; sfargs.shutdownstate = 3; sdargs.signo = 0; sdargs.setsdstate = 3; sdargs.countproc = 0; sdargs.activecount = 0; /* post a SIGTERM to all that catch SIGTERM and not marked for delay */ proc_rebootscan(sd_callback3, (void *)&sdargs, sd_filt2, (void *)&sfargs); printf("\n"); /* Now start the termination of processes that are marked for delayed termn */ if (delayterm == 0) { delayterm = 1; goto sigterm_loop; } sd_closelog(ctx); /* * Now that all other processes have been terminated, suspend init */ task_suspend_internal(initproc->task); /* drop the ref on initproc */ proc_rele(initproc); printf("continuing\n"); }