static int sq_test_random(squeue_t *sq)
{
	unsigned long size, i;
	unsigned long long numbers[EVT_ARY], *d, max = 0;
	struct timeval now;

	size = squeue_size(sq);
	now.tv_sec = time(NULL);
	srand((int)now.tv_sec);
	for (i = 0; i < EVT_ARY; i++) {
		now.tv_usec = (time_t)rand();
		squeue_add_tv(sq, &now, &numbers[i]);
		numbers[i] = evt_compute_pri(&now);
		t(squeue_size(sq) == i + 1 + size);
	}

	t(pqueue_is_valid(sq));

	/*
	 * make sure we pop events in increasing "priority",
	 * since we calculate priority based on time and later
	 * is lower prio
	 */
	for (i = 0; i < EVT_ARY; i++) {
		d = (unsigned long long *)squeue_pop(sq);
		t(max <= *d, "popping randoms. i: %lu; delta: %lld; max: %llu; *d: %llu\n",
		  i, max - *d, max, *d);
		max = *d;
		t(squeue_size(sq) == size + (EVT_ARY - i - 1));
	}
	t(pqueue_is_valid(sq));

	return 0;
}
Example #2
0
squeue_event *squeue_add_usec(squeue_t *q, time_t when, time_t usec, void *data)
{
	struct timeval tv;
	tv.tv_sec = when;
	tv.tv_usec = usec;
	assert(usec < 1000000);
	return squeue_add_tv(q, &tv, data);
}
Example #3
0
squeue_event *squeue_add(squeue_t *q, time_t when, void *data)
{
	struct timeval tv;

	/*
	 * we fetch real microseconds first, so events with same
	 * timestamp get different priorities for FIFO ordering.
	 */
	gettimeofday(&tv, NULL);
	tv.tv_sec = when;

	return squeue_add_tv(q, &tv, data);
}
Example #4
0
/*
 * "What can the harvest hope for, if not for the care
 * of the Reaper Man?"
 *   -- Terry Pratchett, Reaper Man
 *
 * We end up here no matter if the job is stale (ie, the child is
 * stuck in uninterruptable sleep) or if it's the first time we try
 * to kill it.
 * A job is considered reaped once we reap our direct child, in
 * which case init will become parent of our grandchildren.
 * It's also considered fully reaped if kill() results in ESRCH or
 * EPERM, or if wait()ing for the process group results in ECHILD.
 */
static void kill_job(child_process *cp, int reason)
{
	int ret, status, reaped = 0;
	int pid = cp ? cp->ei->pid : 0;

	/*
	 * first attempt at reaping, so see if we just failed to
	 * notice that things were going wrong her
	 */
	if (reason == ETIME && !check_completion(cp, WNOHANG)) {
		timeouts++;
		wlog("job %d with pid %d reaped at timeout. timeouts=%u; started=%u", cp->id, pid, timeouts, started);
		return;
	}

	/* brutal but efficient */
	if (kill(-cp->ei->pid, SIGKILL) < 0) {
		if (errno == ESRCH) {
			reaped = 1;
		} else {
			wlog("kill(-%d, SIGKILL) failed: %s\n", cp->ei->pid, strerror(errno));
		}
	}

	/*
	 * we must iterate at least once, in case kill() returns
	 * ESRCH when there's zombies
	 */
	do {
		ret = waitpid(cp->ei->pid, &status, WNOHANG);
		if (ret < 0 && errno == EINTR)
			continue;

		if (ret == cp->ei->pid || (ret < 0 && errno == ECHILD)) {
			reaped = 1;
			break;
		}
		if (!ret) {
			struct timeval tv;

			gettimeofday(&tv, NULL);
			/*
			 * stale process (signal may not have been delivered, or
			 * the child can be stuck in uninterruptible sleep). We
			 * can't hang around forever, so just reschedule a new
			 * reap attempt later.
			 */
			if (reason == ESTALE) {
				tv.tv_sec += 5;
				wlog("Failed to reap child with pid %d. Next attempt @ %lu.%lu", cp->ei->pid, tv.tv_sec, tv.tv_usec);
			} else {
				tv.tv_usec = 250000;
				if (tv.tv_usec > 1000000) {
					tv.tv_usec -= 1000000;
					tv.tv_sec += 1;
				}
				cp->ei->state = ESTALE;
				finish_job(cp, reason);
			}
			squeue_remove(sq, cp->ei->sq_event);
			cp->ei->sq_event = squeue_add_tv(sq, &tv, cp);
			return;
		}
	} while (!reaped);

	if (cp->ei->state != ESTALE)
		finish_job(cp, reason);
	else
		wlog("job %d (pid=%d): Dormant child reaped", cp->id, cp->ei->pid);
	destroy_job(cp);
}