static inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct user_namespace *user_ns = seq_user_ns(m); struct group_info *group_info; int g; struct fdtable *fdt = NULL; const struct cred *cred; pid_t ppid, tpid; rcu_read_lock(); ppid = pid_alive(p) ? task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; tpid = 0; if (pid_alive(p)) { struct task_struct *tracer = ptrace_parent(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); } cred = get_task_cred(p); seq_printf(m, "State:\t%s\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), task_tgid_nr_ns(p, ns), pid_nr_ns(pid, ns), ppid, tpid, from_kuid_munged(user_ns, cred->uid), from_kuid_munged(user_ns, cred->euid), from_kuid_munged(user_ns, cred->suid), from_kuid_munged(user_ns, cred->fsuid), from_kgid_munged(user_ns, cred->gid), from_kgid_munged(user_ns, cred->egid), from_kgid_munged(user_ns, cred->sgid), from_kgid_munged(user_ns, cred->fsgid)); task_lock(p); if (p->files) fdt = files_fdtable(p->files); seq_printf(m, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); rcu_read_unlock(); group_info = cred->group_info; task_unlock(p); for (g = 0; g < group_info->ngroups; g++) seq_printf(m, "%d ", from_kgid_munged(user_ns, GROUP_AT(group_info, g))); put_cred(cred); seq_putc(m, '\n'); }
static inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct group_info *group_info; int g; struct fdtable *fdt = NULL; const struct cred *cred; pid_t ppid, tpid, vpid; rcu_read_lock(); ppid = pid_alive(p) ? ve_task_ppid_nr_ns(p, ns) : 0; tpid = 0; if (pid_alive(p)) { struct task_struct *tracer = tracehook_tracer_task(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); } vpid = task_virtual_pid(p); cred = get_task_cred(p); seq_printf(m, "State:\t%s\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), task_tgid_nr_ns(p, ns), pid_nr_ns(pid, ns), ppid, tpid, cred->uid, cred->euid, cred->suid, cred->fsuid, cred->gid, cred->egid, cred->sgid, cred->fsgid); task_utrace_proc_status(m, p); task_lock(p); if (p->files) fdt = files_fdtable(p->files); seq_printf(m, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); rcu_read_unlock(); group_info = cred->group_info; task_unlock(p); for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) seq_printf(m, "%d ", GROUP_AT(group_info, g)); put_cred(cred); seq_printf(m, "\n"); seq_printf(m, "envID:\t%d\nVPid:\t%d\n", p->ve_task_info.owner_env->veid, vpid); seq_printf(m, "StopState:\t%u\n", p->stopped_state); }
static inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct group_info *group_info; int g; struct fdtable *fdt = NULL; pid_t ppid, tpid; rcu_read_lock(); ppid = pid_alive(p) ? task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; tpid = 0; if (pid_alive(p)) { struct task_struct *tracer = tracehook_tracer_task(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); } seq_printf(m, "State:\t%s\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), task_tgid_nr_ns(p, ns), pid_nr_ns(pid, ns), ppid, tpid, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); task_lock(p); if (p->files) fdt = files_fdtable(p->files); seq_printf(m, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); rcu_read_unlock(); group_info = p->group_info; get_group_info(group_info); task_unlock(p); for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) seq_printf(m, "%d ", GROUP_AT(group_info, g)); put_group_info(group_info); seq_printf(m, "\n"); }
/* count current worker and jobs */ void count_current_worker(int restart) { int x; gm_log( GM_LOG_TRACE3, "count_current_worker()\n"); gm_log( GM_LOG_TRACE3, "done jobs: shm[SHM_JOBS_DONE] = %d\n", shm[SHM_JOBS_DONE]); /* shm states: * 0 -> undefined * -1 -> free * <-1 -> used but idle * > 1 -> used and working */ /* check if status worker died */ if( shm[SHM_STATUS_WORKER_PID] != -1 && pid_alive(shm[SHM_STATUS_WORKER_PID]) == FALSE ) { gm_log( GM_LOG_TRACE, "removed stale status worker, old pid: %d\n", shm[SHM_STATUS_WORKER_PID] ); shm[SHM_STATUS_WORKER_PID] = -1; } gm_log( GM_LOG_TRACE3, "status worker: shm[SHM_STATUS_WORKER_PID] = %d\n", shm[SHM_STATUS_WORKER_PID]); /* check all known worker */ current_number_of_workers = 0; current_number_of_jobs = 0; for(x=SHM_SHIFT; x < mod_gm_opt->max_worker+SHM_SHIFT; x++) { /* verify worker is alive */ gm_log( GM_LOG_TRACE3, "worker slot: shm[%d] = %d\n", x, shm[x]); if( shm[x] != -1 && pid_alive(shm[x]) == FALSE ) { gm_log( GM_LOG_TRACE, "removed stale worker %d, old pid: %d\n", x, shm[x]); shm[x] = -1; /* immediately start new worker, otherwise the fork rate cannot be guaranteed */ if(restart == GM_ENABLED) { make_new_child(GM_WORKER_MULTI); current_number_of_workers++; } } if(shm[x] != -1) { current_number_of_workers++; } if(shm[x] > 0) { current_number_of_jobs++; } } shm[SHM_WORKER_TOTAL] = current_number_of_workers; /* total worker */ shm[SHM_WORKER_RUNNING] = current_number_of_jobs; /* running worker */ gm_log( GM_LOG_TRACE3, "worker: %d - running: %d\n", current_number_of_workers, current_number_of_jobs); return; }
/* * Check that the processes holding locks are still alive. */ static bool check_lock(lock_t *_lock) { pid_t pid; /* We don't care about unlocked or locking-in-progress */ if (_lock->lock != LOCKED) return FALSE; /* First the easy case. If it's held by a dead pid, release it. */ pid = _lock->owner; /* if we're in the process of unlocking, it can show up as LOCKED * but with no owner. Just bail, we'll try again next time around. */ if (pid == 0) return FALSE; if (pid_alive(pid) == FALSE) { if (errno != ESRCH) return TRUE; debugf("Found a lock held by dead pid %d. Freeing.\n", pid); unlock(_lock); return TRUE; } return FALSE; }
static void check_lock(lock_t *_lock) { pid_t pid; if (_lock->lock != LOCKED) return; /* First the easy case. If it's held by a dead pid, release it. */ pid = _lock->owner; if (pid_alive(pid) == -1) { if (errno != ESRCH) return; debugf("Found a lock held by dead pid %d. Freeing.\n", pid); unlock(_lock); return; } /* If a pid has had a lock a long time, something is up. */ if (_lock->contention > STEAL_THRESHOLD) { debugf("pid %d has held lock for too long. Releasing, and killing.\n", pid); kill_pid(pid); unlock(_lock); return; } return; }
/* send kill to all forked processes */ void kill_child_checks(void) { int retval; pid_t pid; signal(SIGINT, SIG_IGN); pid = getpid(); if(current_child_pid > 0 && current_child_pid != pid) { gm_log( GM_LOG_TRACE, "kill_child_checks(): send SIGINT to %d\n", current_child_pid); kill(-current_child_pid, SIGINT); kill(current_child_pid, SIGINT); sleep(1); if(waitpid(current_child_pid,&retval,WNOHANG)!=0) { signal(SIGINT, SIG_DFL); return; } if(pid_alive(current_child_pid)) { gm_log( GM_LOG_TRACE, "kill_child_checks(): send SIGKILL to %d\n", current_child_pid); kill(current_child_pid, SIGKILL); } } gm_log( GM_LOG_TRACE, "send SIGINT to %d\n", pid); kill(0, SIGINT); signal(SIGINT, SIG_DFL); return; }
/* Main function for TLB walkthrough * Check accessed page every Memmap_wakeupsIinterval ms */ int Moca_MonitorThread(void * arg) { task_data data; moca_task t; struct task_struct * task; //Init tlb walk data int pos; unsigned long long lastwake=0; MOCA_DEBUG_PRINT("Moca monitor thread alive \n"); while(!kthread_should_stop()) { pos=0; while((t=Moca_NextTask(&pos))) { data=t->data; task=(struct task_struct *)(t->key); MOCA_DEBUG_PRINT("Moca monitor thread testing task %p\n", task); if(pid_alive(task) && task->sched_info.last_arrival >= lastwake) { lastwake=task->sched_info.last_arrival; MOCA_DEBUG_PRINT("Moca monitor thread found task %p\n",task); Moca_MonitorPage(data); } } Moca_UpdateClock(); MOCA_DEBUG_PRINT("Moca monitor thread going to sleep for %d\n", Moca_wakeupInterval); msleep(Moca_wakeupInterval); } MOCA_DEBUG_PRINT("Moca monitor thread finished\n"); return 0; }
// Add pid to the monitored process if pid is a monitored process moca_task Moca_AddTaskIfNeeded(struct task_struct *t) { moca_task ret=NULL; if(t && pid_alive(t) && t->real_parent && Moca_ShouldMonitorTask(t)) ret=Moca_AddTask(t); return ret; }
/* * Accumulate raw cputime values of dead tasks (sig->[us]time) and live * tasks (sum on group iteration) belonging to @tsk's group. */ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times) { struct signal_struct *sig = tsk->signal; cputime_t utime, stime; struct task_struct *t; times->utime = sig->utime; times->stime = sig->stime; times->sum_exec_runtime = sig->sum_sched_runtime; rcu_read_lock(); /* make sure we can trust tsk->thread_group list */ if (!likely(pid_alive(tsk))) goto out; t = tsk; do { task_cputime(tsk, &utime, &stime); times->utime += utime; times->stime += stime; times->sum_exec_runtime += task_sched_runtime(t); } while_each_thread(tsk, t); out: rcu_read_unlock(); }
void init_child(int childno) { cpu_set_t set; pid_t pid = getpid(); char childname[17]; this_child = childno; set_seed(childno); shm->kill_count[childno] = 0; shm->num_mappings[childno] = 0; shm->mappings[childno] = zmalloc(sizeof(struct map)); INIT_LIST_HEAD(&shm->mappings[childno]->list); setup_page_maps(); if (sched_getaffinity(pid, sizeof(set), &set) == 0) { CPU_ZERO(&set); CPU_SET(childno, &set); sched_setaffinity(pid, sizeof(set), &set); } shm->child_syscall_count[childno] = 0; memset(childname, 0, sizeof(childname)); sprintf(childname, "trinity-c%d", childno); prctl(PR_SET_NAME, (unsigned long) &childname); oom_score_adj(500); /* Wait for parent to set our pidslot */ while (shm->pids[childno] != getpid()) { int ret = 0; /* Make sure parent is actually alive to wait for us. */ ret = pid_alive(shm->mainpid); if (ret != 0) { shm->exit_reason = EXIT_SHM_CORRUPTION; outputerr(BUGTXT "parent (%d) went away!\n", shm->mainpid); sleep(20000); } } /* Wait for all the children to start up. */ while (shm->ready == FALSE) sleep(1); set_make_it_fail(); if (rand() % 100 < 50) use_fpu(); mask_signals_child(); disable_coredumps(); }
static inline char * task_state(struct task_struct *p, char *buffer) { struct group_info *group_info; int g; struct fdtable *fdt = NULL; read_lock(&tasklist_lock); buffer += sprintf(buffer, "State:\t%s\n" "SleepAVG:\t%lu%%\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), (p->sleep_avg/1024)*100/(1020000000/1024), p->tgid, p->pid, pid_alive(p) ? p->group_leader->real_parent->tgid : 0, pid_alive(p) && p->ptrace ? p->parent->pid : 0, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); task_lock(p); rcu_read_lock(); if (p->files) fdt = files_fdtable(p->files); buffer += sprintf(buffer, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); rcu_read_unlock(); group_info = p->group_info; get_group_info(group_info); task_unlock(p); for (g = 0; g < min(group_info->ngroups,NGROUPS_SMALL); g++) buffer += sprintf(buffer, "%d ", GROUP_AT(group_info,g)); put_group_info(group_info); buffer += sprintf(buffer, "\n"); return buffer; }
static inline void task_state(struct seq_file *m, struct pid *pid, struct task_struct *p) { struct group_info *group_info; int g; struct fdtable *fdt = NULL; rcu_read_lock(); seq_printf(m, "State:\t%s\n" "SleepAVG:\t%lu%%\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), (p->sleep_avg/1024)*100/(1020000000/1024), p->tgid, p->pid, pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0, pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); task_lock(p); if (p->files) fdt = files_fdtable(p->files); seq_printf(m, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); rcu_read_unlock(); group_info = p->group_info; get_group_info(group_info); task_unlock(p); for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) seq_printf(m, "%d ", GROUP_AT(group_info, g)); put_group_info(group_info); seq_printf(m, "\n"); }
/* This is a special case for things like execve, which would replace our * child process with something unknown to us. We use a 'throwaway' process * to do the execve in, and let it run for a max of a second before we kill it */ static void do_extrafork(struct syscallrecord *rec) { pid_t pid = 0; pid_t extrapid; extrapid = fork(); if (extrapid == 0) { /* grand-child */ char childname[]="trinity-subchild"; prctl(PR_SET_NAME, (unsigned long) &childname); __do_syscall(rec, GOING_AWAY); /* if this was for eg. an successful execve, we should never get here. * if it failed though... */ _exit(EXIT_SUCCESS); } /* misc failure. */ if (extrapid == -1) { //debugf("Couldn't fork grandchild: %s\n", strerror(errno)); return; } /* small pause to let grandchild do some work. */ if (pid_alive(extrapid) == TRUE) usleep(100); /* We take the rec lock here even though we don't obviously use it. * The reason, is that the grandchild is using it. */ lock(&rec->lock); while (pid == 0) { int childstatus; pid = waitpid(extrapid, &childstatus, WUNTRACED | WCONTINUED | WNOHANG); if (pid_alive(extrapid) == TRUE) kill(extrapid, SIGKILL); usleep(1000); } unlock(&rec->lock); }
void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) { const struct cred *tcred; struct timespec uptime, ts; u64 ac_etime; BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN); do_posix_clock_monotonic_gettime(&uptime); ts = timespec_sub(uptime, tsk->start_time); ac_etime = timespec_to_ns(&ts); do_div(ac_etime, NSEC_PER_USEC); stats->ac_etime = ac_etime; stats->ac_btime = get_seconds() - ts.tv_sec; if (thread_group_leader(tsk)) { stats->ac_exitcode = tsk->exit_code; if (tsk->flags & PF_FORKNOEXEC) stats->ac_flag |= AFORK; } if (tsk->flags & PF_SUPERPRIV) stats->ac_flag |= ASU; if (tsk->flags & PF_DUMPCORE) stats->ac_flag |= ACORE; if (tsk->flags & PF_SIGNALED) stats->ac_flag |= AXSIG; stats->ac_nice = task_nice(tsk); stats->ac_sched = tsk->policy; stats->ac_pid = tsk->pid; rcu_read_lock(); tcred = __task_cred(tsk); stats->ac_uid = tcred->uid; stats->ac_gid = tcred->gid; stats->ac_ppid = pid_alive(tsk) ? rcu_dereference(tsk->real_parent)->tgid : 0; rcu_read_unlock(); stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC; stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC; stats->ac_utimescaled = cputime_to_msecs(tsk->utimescaled) * USEC_PER_MSEC; stats->ac_stimescaled = cputime_to_msecs(tsk->stimescaled) * USEC_PER_MSEC; stats->ac_minflt = tsk->min_flt; stats->ac_majflt = tsk->maj_flt; strncpy(stats->ac_comm, tsk->comm, sizeof(stats->ac_comm)); }
static void timer_function(unsigned long par) { ushort cpu_share; if (unlikely(!pid_alive(check_task))) { del_timer(&check_timer); printk(KERN_INFO "sendsig: cannot find pid %i. Is the process still active? Timer removed\n", pid); return; } cpu_share = thread_group_cpu_share(check_task); if (cpu_share >= max_cpu_share) { count_check++; printk(KERN_INFO "sendsig: current cpu share over limit of %i (check #%i)\n", max_cpu_share, count_check); /* the ratio is: if the process has a cpu share higher than max_cpu_share for more than max_checks * wait_timeout seconds, then we'll send the signal sig_to_send to it */ if (count_check >= max_checks) { /* sending the signal to the process */ signal_send(check_task); /* remove the timer */ del_timer(&check_timer); printk(KERN_INFO "sendsig: sent signal to process %i, timer removed\n", pid); return; } } else { /* if the process is being good, let's reset its counter */ count_check = 0; } /* update the timer */ mod_timer(&check_timer, jiffies + wait_timeout * HZ); return; }
static void restart_lost_procs(void) { svc_t *svc; for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) { if (svc->pid > 0 && pid_alive(svc->pid)) continue; /* Only restart lost daemons, not task/run/inetd services */ if (SVC_TYPE_SERVICE != svc->type) { svc->pid = 0; continue; } service_start(svc); } }
static void post_fork(struct syscallrecord *rec) { pid_t pid; pid = rec->retval; if (pid == 0) { // child sleep(1); _exit(EXIT_SUCCESS); } else { __unused__ int ret; while (pid_alive(pid)) { int status; ret = waitpid(pid, &status, WUNTRACED | WCONTINUED | WNOHANG); } } }
static inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct group_info *group_info; int g; struct fdtable *fdt = NULL; const struct cred *cred; pid_t ppid, tpid; rcu_read_lock(); ppid = pid_alive(p) ? task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; tpid = 0; if (pid_alive(p)) { <<<<<<< HEAD struct task_struct *tracer = ptrace_parent(p); ======= <<<<<<< HEAD
static void post_fork(int childno) { pid_t pid; pid = shm->syscall[childno].retval; if (pid == 0) { // child sleep(1); _exit(EXIT_SUCCESS); } else { __unused__ int ret; while (pid_alive(pid)) { int status; ret = waitpid(pid, &status, WUNTRACED | WCONTINUED | WNOHANG); } } }
int monitor_fn(void* unused) { tm->target_task = get_pid_task(tm->target_pid, PIDTYPE_PID); while(tm->target_task && pid_alive(tm->target_task) && !kthread_should_stop()){ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); pr_info("taskmonitor: pid %d\tusr %d\tsys %d\n", target, (int)tm->target_task->utime, (int)tm->target_task->stime); } if(tm->target_task) put_task_struct(tm->target_task); pr_warn("monitor_fn: target task is no longer alive !\n"); return 0; }
void lock(lock_t *_lock) { while (_lock->lock == LOCKED) { _lock->contention++; usleep(1); if (_lock->contention > STEAL_THRESHOLD) { pid_t pid = _lock->owner; if (pid_alive(pid) == FALSE) { output(0, "[%d] more than %d attempts to get lock. pid %d looks dead, stealing.\n", getpid(), STEAL_THRESHOLD, pid); goto steal; } } } steal: _lock->contention = 0; _lock->lock = LOCKED; _lock->owner = getpid(); }
/* Used by wait */ static void wait_checker(struct work_struct *w) { struct delayed_work * w_del; struct wait_struct * w_stru; int i; w_del = to_delayed_work(w); w_stru = container_of(w_del, struct wait_struct, w_delayed); wake_up_interruptible(&waiter); for (i = 0; i < w_stru->w_size; i++) { if (!pid_alive(w_stru->w_pids[i])) { w_stru->w_is_finished = i; wake_up_interruptible(&waiter); return; } } /* On relance la boucle */ queue_delayed_work(syndicate, &(wOs->w_dw), TICKS_DELAY); }
void dump_childnos(void) { unsigned int i, j = 0; char string[512], *sptr = string; sptr += sprintf(sptr, "## pids: (%u active)\n", shm->running_childs); for (i = 0; i < max_children; i += 8) { sptr += sprintf(sptr, "%u-%u: ", i, i + 7); for (j = 0; j < 8; j++) { struct childdata *child; if (i + j > max_children) break; child = shm->children[i + j]; if (pids[child->num] == EMPTY_PIDSLOT) { sptr += sprintf(sptr, "[empty] "); } else { pid_t pid = pids[child->num]; if (pid_is_valid(pid) == FALSE) sptr += sprintf(sptr, "%s", ANSI_RED); if (pid_alive(pid) == FALSE) sptr += sprintf(sptr, "%s", ANSI_RED); sptr += sprintf(sptr, "%u %s", pid, ANSI_RESET); } } sptr += sprintf(sptr, "\n"); *sptr = '\0'; outputerr("%s", string); sptr = string; } }
static void fork_children(void) { int pidslot; static char childname[17]; /* Generate children*/ while (shm->running_childs < shm->max_children) { int pid = 0; /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { printf("[%d] ## Pid map was full!\n", getpid()); dump_pid_slots(); exit(EXIT_FAILURE); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid != 0) shm->pids[pidslot] = pid; else { /* Child process. */ int ret = 0; mask_signals_child(); memset(childname, 0, sizeof(childname)); sprintf(childname, "trinity-child%d", pidslot); prctl(PR_SET_NAME, (unsigned long) &childname); oom_score_adj(500); /* Wait for parent to set our pidslot */ while (shm->pids[pidslot] != getpid()) { /* Make sure parent is actually alive to wait for us. */ ret = pid_alive(shm->parentpid); if (ret != 0) { shm->exit_reason = EXIT_SHM_CORRUPTION; printf("[%d] " BUGTXT "parent (%d) went away!\n", getpid(), shm->parentpid); sleep(20000); } } init_child(pidslot); ret = child_process(pidslot); output(1, "child %d exiting\n", getpid()); _exit(ret); } shm->running_childs++; debugf("[%d] Created child %d in pidslot %d [total:%d/%d]\n", getpid(), shm->pids[pidslot], pidslot, shm->running_childs, shm->max_children); if (shm->exit_reason != STILL_RUNNING) return; } debugf("[%d] created enough children\n", getpid()); }
/* main tests */ int main (int argc, char **argv, char **env) { argc = argc; argv = argv; env = env; int status, chld, rc; int tests = 125; int rrc; char cmd[150]; char *result, *error, *message, *output; plan(tests); mod_gm_opt = malloc(sizeof(mod_gm_opt_t)); set_default_options(mod_gm_opt); #ifdef EMBEDDEDPERL char p1[150]; snprintf(p1, 150, "--p1_file=worker/mod_gearman_p1.pl"); parse_args_line(mod_gm_opt, p1, 0); init_embedded_perl(env); #endif char options[150]; snprintf(options, 150, "--server=127.0.0.1:%d", GEARMAND_TEST_PORT); ok(parse_args_line(mod_gm_opt, options, 0) == 0, "parse_args_line()"); mod_gm_opt->debug_level = GM_LOG_ERROR; worker_logfile = my_tmpfile(); if(!ok(worker_logfile != NULL, "created temp logile: %s", worker_logfile)) { diag("could not create temp logfile"); exit( EXIT_FAILURE ); } /* first fire up a gearmand server and one worker */ start_gearmand((void*)NULL); sleep(2); start_worker((void*)NULL); sleep(2); /* wait one second and catch died procs */ while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) { diag( "waitpid() %d exited with %d\n", chld, status); status = 0; } if(!ok(gearmand_pid > 0, "'gearmand started with port %d and pid: %d", GEARMAND_TEST_PORT, gearmand_pid)) { diag("make sure gearmand is in your PATH. Common locations are /usr/sbin or /usr/local/sbin"); exit( EXIT_FAILURE ); } if(!ok(pid_alive(gearmand_pid) == TRUE, "gearmand alive")) { check_logfile("/tmp/gearmand.log", 3); kill(gearmand_pid, SIGTERM); kill(worker_pid, SIGTERM); exit( EXIT_FAILURE ); } if(!ok(worker_pid > 0, "worker started with pid: %d", worker_pid)) diag("could not start worker"); if(!ok(pid_alive(worker_pid) == TRUE, "worker alive")) { check_logfile(worker_logfile, 3); kill(gearmand_pid, SIGTERM); kill(worker_pid, SIGTERM); exit( EXIT_FAILURE ); } skip(gearmand_pid <= 0 || worker_pid <= 0, tests-3, /* Number of tests to skip */ "Skipping all tests, no need to go on without gearmand or worker"); /* create server / clients */ mod_gm_opt->transportmode = GM_ENCODE_ONLY; create_modules(); /* send big job */ send_big_jobs(GM_ENCODE_ONLY); //diag_queues(); wait_for_empty_queue("eventhandler", 20); wait_for_empty_queue("service", 20); //diag_queues(); do_result_work(1); //diag_queues(); wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5); /***************************************** * test check */ //diag_queues(); test_servicecheck(GM_ENCODE_ONLY, "./t/crit.pl"); //diag_queues(); wait_for_empty_queue("eventhandler", 20); wait_for_empty_queue("service", 5); //diag_queues(); do_result_work(1); //diag_queues(); wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5); //diag_queues(); like(last_result, "test plugin CRITICAL", "stdout output from ./t/crit.pl"); like(last_result, "some errors on stderr", "stderr output from ./t/crit.pl"); /***************************************** * test check2 */ //diag_queues(); test_servicecheck(GM_ENCODE_ONLY, "./t/both"); //diag_queues(); wait_for_empty_queue("eventhandler", 20); wait_for_empty_queue("service", 5); //diag_queues(); do_result_work(1); //diag_queues(); wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5); like(last_result, "stdout output", "stdout output from ./t/both"); like(last_result, "stderr output", "stderr output from ./t/both"); /* try to send some data with base64 only */ //diag_queues(); test_eventhandler(GM_ENCODE_ONLY); //diag_queues(); test_servicecheck(GM_ENCODE_ONLY, NULL); //diag_queues(); wait_for_empty_queue("eventhandler", 20); wait_for_empty_queue("service", 5); //diag_queues(); do_result_work(1); //diag_queues(); wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5); sleep(1); kill(worker_pid, SIGTERM); waitpid(worker_pid, &status, 0); ok(status == 0, "worker (%d) exited with exit code %d", worker_pid, real_exit_code(status)); status = 0; check_no_worker_running(worker_logfile); check_logfile(worker_logfile, 0); char * test_keys[] = { "12345", "test", "test key 123", "me make you loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong key" }; /* ignore some signals for now */ signal(SIGTERM, SIG_IGN); int i; for(i=0;i<4;i++) { mod_gm_opt->transportmode = GM_ENCODE_AND_ENCRYPT; start_worker((void *)test_keys[i]); mod_gm_crypt_init( test_keys[i] ); ok(1, "initialized with key: %s", test_keys[i]); test_eventhandler(GM_ENCODE_AND_ENCRYPT); test_servicecheck(GM_ENCODE_AND_ENCRYPT, NULL); wait_for_empty_queue("eventhandler", 20); wait_for_empty_queue("service", 5); do_result_work(1); wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5); sleep(1); kill(worker_pid, SIGTERM); waitpid(worker_pid, &status, 0); ok(status == 0, "worker (%d) exited with exit code %d", worker_pid, real_exit_code(status)); status = 0; check_no_worker_running(worker_logfile); check_logfile(worker_logfile, 0); } /***************************************** * send_gearman */ snprintf(cmd, 150, "./send_gearman --server=127.0.0.1:%d --key=testtest --host=test --service=test --message=test --returncode=0", GEARMAND_TEST_PORT); rrc = real_exit_code(run_check(cmd, &result, &error)); cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc); like(result, "^\\s*$", "output from ./send_gearman"); free(result); free(error); /***************************************** * send_multi */ snprintf(cmd, 150, "./send_multi --server=127.0.0.1:%d --host=blah < t/data/send_multi.txt", GEARMAND_TEST_PORT); rrc = real_exit_code(run_check(cmd, &result, &error)); cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc); like(result, "send_multi OK: 2 check_multi child checks submitted", "output from ./send_multi"); free(result); free(error); /***************************************** * check_gearman */ snprintf(cmd, 150, "./check_gearman -H 127.0.0.1:%d -s check -a -q worker_test", GEARMAND_TEST_PORT); rrc = real_exit_code(run_check(cmd, &result, &error)); cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc); like(result, "check_gearman OK - sending background job succeded", "output from ./check_gearman"); /* cleanup */ free(result); free(error); free_client(&client); free_worker(&worker); /* shutdown gearmand */ rc = send2gearmandadmin("shutdown\n", "127.0.0.1", GEARMAND_TEST_PORT, &output, &message); ok(rc == 0, "rc of send2gearmandadmin %d", rc); like(output, "OK", "output contains OK"); free(message); free(output); /* wait 5 seconds to shutdown */ for(i=0;i<=5;i++) { waitpid(gearmand_pid, &status, WNOHANG); if(pid_alive(gearmand_pid) == FALSE) { todo(); ok(status == 0, "gearmand (%d) exited with: %d", gearmand_pid, real_exit_code(status)); endtodo; break; } sleep(1); } if(pid_alive(gearmand_pid) == TRUE) { /* kill it the hard way */ kill(gearmand_pid, SIGTERM); waitpid(gearmand_pid, &status, 0); ok(status == 0, "gearmand (%d) exited with exit code %d", gearmand_pid, real_exit_code(status)); status = 0; ok(false, "gearmand had to be killed!"); } todo(); check_logfile("/tmp/gearmand.log", status != 0 ? 2 : 0); endtodo; status = 0; kill(worker_pid, SIGTERM); waitpid(worker_pid, &status, 0); ok(status == 0, "worker (%d) exited with exit code %d", worker_pid, real_exit_code(status)); check_no_worker_running(worker_logfile); status = 0; #ifdef EMBEDDEDPERL deinit_embedded_perl(0); #endif free(last_result); free(worker_logfile); endskip; mod_gm_free_opt(mod_gm_opt); return exit_status(); }
static void handle_child(pid_t childpid, int childstatus) { switch (childpid) { case 0: //debugf("Nothing changed. children:%d\n", shm->running_childs); break; case -1: if (shm->exit_reason != STILL_RUNNING) return; if (errno == ECHILD) { unsigned int i; bool seen = FALSE; debugf("All children exited!\n"); for_each_child(i) { struct childdata *child; child = shm->children[i]; if (child->pid != EMPTY_PIDSLOT) { if (pid_alive(child->pid) == -1) { debugf("Removing %d from pidmap\n", child->pid); child->pid = EMPTY_PIDSLOT; shm->running_childs--; } else { debugf("%d looks still alive! ignoring.\n", child->pid); } seen = TRUE; } } if (seen == FALSE) shm->running_childs = 0; break; } output(0, "error! (%s)\n", strerror(errno)); break; default: debugf("Something happened to pid %d\n", childpid); if (WIFEXITED(childstatus)) { int childno; childno = find_childno(childpid); if (childno != CHILD_NOT_FOUND) { debugf("Child %d exited after %ld operations.\n", childpid, shm->children[childno]->syscall.op_nr); reap_child(childpid); } break; } else if (WIFSIGNALED(childstatus)) { handle_childsig(childpid, childstatus, FALSE); } else if (WIFSTOPPED(childstatus)) { handle_childsig(childpid, childstatus, TRUE); } else if (WIFCONTINUED(childstatus)) { break; } else { output(0, "erk, wtf\n"); } }
static void fork_children(void) { int pidslot; static char childname[17]; /* Generate children*/ while (shm->running_childs < shm->max_children) { int pid = 0; int fd; if (shm->spawn_no_more == TRUE) return; /* a new child means a new seed, or the new child * will do the same syscalls as the one in the pidslot it's replacing. * (special case startup, or we reseed unnecessarily) */ if (shm->ready == TRUE) reseed(); /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { outputerr("## Pid map was full!\n"); dump_pid_slots(); exit(EXIT_FAILURE); } if (logging == TRUE) { fd = fileno(shm->logfiles[pidslot]); if (ftruncate(fd, 0) == 0) lseek(fd, 0, SEEK_SET); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid != 0) shm->pids[pidslot] = pid; else { /* Child process. */ int ret = 0; mask_signals_child(); memset(childname, 0, sizeof(childname)); sprintf(childname, "trinity-child%d", pidslot); prctl(PR_SET_NAME, (unsigned long) &childname); oom_score_adj(500); /* Wait for parent to set our pidslot */ while (shm->pids[pidslot] != getpid()) { /* Make sure parent is actually alive to wait for us. */ ret = pid_alive(shm->mainpid); if (ret != 0) { shm->exit_reason = EXIT_SHM_CORRUPTION; outputerr(BUGTXT "parent (%d) went away!\n", shm->mainpid); sleep(20000); } } /* Wait for all the children to start up. */ while (shm->ready == FALSE) sleep(1); init_child(pidslot); ret = child_process(pidslot); output(1, "child exiting.\n"); _exit(ret); } shm->running_childs++; debugf("Created child %d in pidslot %d [total:%d/%d]\n", shm->pids[pidslot], pidslot, shm->running_childs, shm->max_children); if (shm->exit_reason != STILL_RUNNING) return; } shm->ready = TRUE; debugf("created enough children\n"); }
static void handle_child(pid_t childpid, int childstatus) { unsigned int i; int slot; switch (childpid) { case 0: //debugf("Nothing changed. children:%d\n", shm->running_childs); break; case -1: if (shm->exit_reason != STILL_RUNNING) return; if (errno == ECHILD) { debugf("All children exited!\n"); for_each_pidslot(i) { if (shm->pids[i] != EMPTY_PIDSLOT) { if (pid_alive(shm->pids[i]) == -1) { debugf("Removing %d from pidmap\n", shm->pids[i]); shm->pids[i] = EMPTY_PIDSLOT; shm->running_childs--; } else { debugf("%d looks still alive! ignoring.\n", shm->pids[i]); } } } break; } output(0, "error! (%s)\n", strerror(errno)); break; default: debugf("Something happened to pid %d\n", childpid); if (WIFEXITED(childstatus)) { slot = find_pid_slot(childpid); if (slot == PIDSLOT_NOT_FOUND) { /* If we reaped it, it wouldn't show up, so check that. */ if (shm->last_reaped != childpid) { outputerr("## Couldn't find pid slot for %d\n", childpid); shm->exit_reason = EXIT_LOST_PID_SLOT; dump_pid_slots(); } } else { debugf("Child %d exited after %ld syscalls.\n", childpid, shm->child_syscall_count[slot]); reap_child(childpid); } break; } else if (WIFSIGNALED(childstatus)) { switch (WTERMSIG(childstatus)) { case SIGALRM: debugf("got a alarm signal from pid %d\n", childpid); break; case SIGFPE: case SIGSEGV: case SIGKILL: case SIGPIPE: case SIGABRT: debugf("got a signal from pid %d (%s)\n", childpid, strsignal(WTERMSIG(childstatus))); reap_child(childpid); break; default: debugf("** Child got an unhandled signal (%d)\n", WTERMSIG(childstatus)); break; } break; } else if (WIFSTOPPED(childstatus)) { switch (WSTOPSIG(childstatus)) { case SIGALRM: debugf("got an alarm signal from pid %d\n", childpid); break; case SIGSTOP: debugf("Sending PTRACE_DETACH (and then KILL)\n"); ptrace(PTRACE_DETACH, childpid, NULL, NULL); kill(childpid, SIGKILL); reap_child(childpid); break; case SIGFPE: case SIGSEGV: case SIGKILL: case SIGPIPE: case SIGABRT: debugf("Child %d was stopped by %s\n", childpid, strsignal(WTERMSIG(childstatus))); reap_child(childpid); break; default: debugf("Child %d was stopped by unhandled signal (%s).\n", childpid, strsignal(WSTOPSIG(childstatus))); break; } break; } else if (WIFCONTINUED(childstatus)) { break; } else { output(0, "erk, wtf\n"); } }
static inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct user_namespace *user_ns = seq_user_ns(m); struct group_info *group_info; int g; struct task_struct *tracer; const struct cred *cred; pid_t ppid, tpid = 0, tgid, ngid; unsigned int max_fds = 0; rcu_read_lock(); ppid = pid_alive(p) ? task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; tracer = ptrace_parent(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); tgid = task_tgid_nr_ns(p, ns); ngid = task_numa_group_id(p); cred = get_task_cred(p); task_lock(p); if (p->files) max_fds = files_fdtable(p->files)->max_fds; task_unlock(p); rcu_read_unlock(); seq_printf(m, "State:\t%s\n" "Tgid:\t%d\n" "Ngid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n" "FDSize:\t%d\nGroups:\t", get_task_state(p), tgid, ngid, pid_nr_ns(pid, ns), ppid, tpid, from_kuid_munged(user_ns, cred->uid), from_kuid_munged(user_ns, cred->euid), from_kuid_munged(user_ns, cred->suid), from_kuid_munged(user_ns, cred->fsuid), from_kgid_munged(user_ns, cred->gid), from_kgid_munged(user_ns, cred->egid), from_kgid_munged(user_ns, cred->sgid), from_kgid_munged(user_ns, cred->fsgid), max_fds); group_info = cred->group_info; for (g = 0; g < group_info->ngroups; g++) seq_printf(m, "%d ", from_kgid_munged(user_ns, GROUP_AT(group_info, g))); put_cred(cred); #ifdef CONFIG_PID_NS seq_puts(m, "\nNStgid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_tgid_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSpid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_pid_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSpgid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_pgrp_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSsid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_session_nr_ns(p, pid->numbers[g].ns)); #endif seq_putc(m, '\n'); }