void FProcState::Wait()
{
	if (bHasBeenWaitedFor)
	{
		return;	// we could try waitpid() another time, but why
	}

	for(;;)	// infinite loop in case we get EINTR and have to repeat
	{
		siginfo_t SignalInfo;
		if (waitid(P_PID, GetProcessId(), &SignalInfo, WEXITED))
		{
			if (errno != EINTR)
			{
				int ErrNo = errno;
				UE_LOG(LogHAL, Fatal, TEXT("FLinuxPlatformProcess::WaitForProc: waitid for pid %d failed (errno=%d, %s)"), 
					static_cast< int32 >(GetProcessId()), ErrNo, ANSI_TO_TCHAR(strerror(ErrNo)));
				break;	// exit the loop if for some reason Fatal log (above) returns
			}
		}
		else
		{
			check(SignalInfo.si_pid == GetProcessId());

			ReturnCode = (SignalInfo.si_code == CLD_EXITED) ? SignalInfo.si_status : -1;
			bHasBeenWaitedFor = true;
			bIsRunning = false;	// set in advance
			break;
		}
	}
}
Exemple #2
0
// Block until child_pid exits, then exit. Try to preserve the exit code.
static void WaitForChildAndExit(pid_t child_pid) {
  int exit_code = -1;
  siginfo_t reaped_child_info;

  // Don't "Core" on SIGABRT. SIGABRT is sent by the Chrome OS session manager
  // when things are hanging.
  // Here, the current process is going to waitid() and _exit(), so there is no
  // point in generating a crash report. The child process is the one
  // blocking us.
  if (signal(SIGABRT, ExitWithErrorSignalHandler) == SIG_ERR) {
    FatalError("Failed to change signal handler");
  }

  int wait_ret =
      HANDLE_EINTR(waitid(P_PID, child_pid, &reaped_child_info, WEXITED));

  if (!wait_ret && reaped_child_info.si_pid == child_pid) {
    if (reaped_child_info.si_code == CLD_EXITED) {
      exit_code = reaped_child_info.si_status;
    } else {
      // Exit with code 0 if the child got signaled.
      exit_code = 0;
    }
  }
  _exit(exit_code);
}
Exemple #3
0
/*
 * helper function to wait on process exit or background the job
 */
void queue_job(job_t *job) {
	siginfo_t si;
	if (job->bg) {
		job->state = RUNNING;
		job_add(&root, job);
	} else {
		fg = job;
		si.si_pid = 0;
		waitid(P_PID, job->pid, &si, WEXITED|WSTOPPED);
		tcsetpgrp(0, s_pgid);
		if (si.si_pid != 0) {
			switch (si.si_code) {
				case CLD_EXITED:
					job_rm(&root, fg);
					job_free(&fg);
					break;
				case CLD_STOPPED:
					job->state = STOPPED;
					job_add(&root, fg);
					fg = NULL;
					break;
			}
		}
	}
}
Exemple #4
0
void
event_child_signal(int sig_num)
	{
	siginfo_t	siginfo;
	int			retval;
	Event		*event;
	SList		*list;

	siginfo.si_pid = 0;
	retval = waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG);
	if (pikrellcam.verbose)
		printf("child exit: ret=%d pid=%d %m\n", retval, siginfo.si_pid);

	pthread_mutex_lock(&event_mutex);
	for (list = event_list; list; list = list->next)
		{
		event = (Event *) list->data;
		if (event->child_pid == siginfo.si_pid)
			{
			event->time = pikrellcam.t_now;
			break;
			}
		}
	pthread_mutex_unlock(&event_mutex);
	}
Exemple #5
0
void kill_childs()
{
	siginfo_t info;

	struct web_client *w;
	for(w = web_clients; w ; w = w->next) {
		debug(D_EXIT, "Stopping web client %s", w->client_ip);
		pthread_cancel(w->thread);
		pthread_join(w->thread, NULL);
	}

	int i;
	for (i = 0; static_threads[i].name != NULL ; i++) {
		if(static_threads[i].thread) {
			debug(D_EXIT, "Stopping %s thread", static_threads[i].name);
			pthread_cancel(*static_threads[i].thread);
			pthread_join(*static_threads[i].thread, NULL);
			static_threads[i].thread = NULL;
		}
	}

	if(tc_child_pid) {
		info("Killing tc-qos-helper procees");
		if(killpid(tc_child_pid, SIGTERM) != -1)
			waitid(P_PID, (id_t) tc_child_pid, &info, WEXITED);
	}
	tc_child_pid = 0;

	struct plugind *cd;
	for(cd = pluginsd_root ; cd ; cd = cd->next) {
		debug(D_EXIT, "Stopping %s plugin thread", cd->id);
		pthread_cancel(cd->thread);
		pthread_join(cd->thread, NULL);

		if(cd->pid && !cd->obsolete) {
			debug(D_EXIT, "killing %s plugin process", cd->id);
			if(killpid(cd->pid, SIGTERM) != -1)
				waitid(P_PID, (id_t) cd->pid, &info, WEXITED);
		}
	}

	// if, for any reason there is any child exited
	// catch it here
	waitid(P_PID, 0, &info, WEXITED|WNOHANG);

	debug(D_EXIT, "All threads/childs stopped.");
}
static bool ReapOneProcess() {
    siginfo_t siginfo = {};
    // This returns a zombie pid or informs us that there are no zombies left to be reaped.
    // It does NOT reap the pid; that is done below.
    if (TEMP_FAILURE_RETRY(waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG | WNOWAIT)) != 0) {
        PLOG(ERROR) << "waitid failed";
        return false;
    }

    auto pid = siginfo.si_pid;
    if (pid == 0) return false;

    // At this point we know we have a zombie pid, so we use this scopeguard to reap the pid
    // whenever the function returns from this point forward.
    // We do NOT want to reap the zombie earlier as in Service::Reap(), we kill(-pid, ...) and we
    // want the pid to remain valid throughout that (and potentially future) usages.
    auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); });

    std::string name;
    std::string wait_string;
    Service* service = nullptr;

    if (PropertyChildReap(pid)) {
        name = "Async property child";
    } else if (SubcontextChildReap(pid)) {
        name = "Subcontext";
    } else {
        service = ServiceList::GetInstance().FindService(pid, &Service::pid);

        if (service) {
            name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid);
            if (service->flags() & SVC_EXEC) {
                auto exec_duration = boot_clock::now() - service->time_started();
                auto exec_duration_ms =
                    std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();
                wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
            }
        } else {
            name = StringPrintf("Untracked pid %d", pid);
        }
    }

    auto status = siginfo.si_status;
    if (WIFEXITED(status)) {
        LOG(INFO) << name << " exited with status " << WEXITSTATUS(status) << wait_string;
    } else if (WIFSIGNALED(status)) {
        LOG(INFO) << name << " killed by signal " << WTERMSIG(status) << wait_string;
    }

    if (!service) return true;

    service->Reap();

    if (service->flags() & SVC_TEMPORARY) {
        ServiceList::GetInstance().RemoveService(*service);
    }

    return true;
}
Exemple #7
0
/*
 *  stress_wait
 *	stress wait*() family of calls
 */
int stress_wait(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	int status, ret = EXIT_SUCCESS;
	pid_t pid_r, pid_k;

	(void)instance;

	pr_dbg(stderr, "%s: waiter started [%d]\n",
		name, getpid());

	pid_r = spawn(name, runner, 0, counter, max_ops);
	if (pid_r < 0) {
		pr_fail_dbg(name, "fork");
		exit(EXIT_FAILURE);
	}

	pid_k = spawn(name, killer, pid_r, counter, max_ops);
	if (pid_k < 0) {
		pr_fail_dbg(name, "fork");
		ret = EXIT_FAILURE;
		goto tidy;
	}

	do {
		(void)waitpid(pid_r, &status, WCONTINUED);
		if (!opt_do_run)
			break;
		if (WIFCONTINUED(status))
			(*counter)++;

#if _SVID_SOURCE || _XOPEN_SOURCE >= 500 || \
    _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || \
    _POSIX_C_SOURCE >= 200809L
		{
			siginfo_t info;

			(void)waitid(P_PID, pid_r, &info, WCONTINUED);
			if (!opt_do_run)
				break;
			if (WIFCONTINUED(status))
				(*counter)++;
		}
#endif
	} while (opt_do_run && (!max_ops || *counter < max_ops));

	(void)kill(pid_k, SIGKILL);
	(void)waitpid(pid_k, &status, 0);
tidy:
	(void)kill(pid_r, SIGKILL);
	(void)waitpid(pid_r, &status, 0);

	return ret;
}
static void wait_until_process_exited(pid_t pid, siginfo_t *si)
{
    siginfo_t ignored_si;
    if (NULL == si) {
        si = &ignored_si;
    }
    memset(si, 0, sizeof(*si));
    TRACE_ASSERT(0 == TEMP_FAILURE_RETRY(waitid(P_PID, pid, si, WEXITED)));
}
Exemple #9
0
static void _handle_sig_child(void) {
    siginfo_t info;
    memset(&info, 0, sizeof(info));
    if (0 > waitid(P_ALL, 0, &info, WEXITED | WNOWAIT | WNOHANG))
        return LOGGER_PERROR("waitid");
    if (info.si_pid > 0) {
        LOGGER_ERROR("child process [%d] terminated unexpectedly: %s, status=%d", info.si_pid, _get_exit_reason(&info), info.si_status);
        epoll_worker_exit();
    }
}
Exemple #10
0
pid_t
_waitpid(pid_t pid, int *stat_loc, int options)
{
	idtype_t idtype;
	id_t id;
	siginfo_t info;
	int error;

	if (pid > 0) {
		idtype = P_PID;
		id = pid;
	} else if (pid < -1) {
		idtype = P_PGID;
		id = -pid;
	} else if (pid == -1) {
		idtype = P_ALL;
		id = 0;
	} else {
		idtype = P_PGID;
		id = getpgid(0);
	}

	options |= (WEXITED|WTRAPPED);

	if ((error = waitid(idtype, id, &info, options)) < 0)
		return (error);

	if (stat_loc) {

		int stat = (info.si_status & 0377);

		switch (info.si_code) {
		case CLD_EXITED:
			stat <<= 8;
			break;
		case CLD_DUMPED:
			stat |= WCOREFLG;
			break;
		case CLD_KILLED:
			break;
		case CLD_TRAPPED:
		case CLD_STOPPED:
			stat <<= 8;
			stat |= WSTOPFLG;
			break;
		case CLD_CONTINUED:
			stat = WCONTFLG;
			break;
		}

		*stat_loc = stat;
	}

	return (info.si_pid);
}
Exemple #11
0
static siginfo_t wait_trap(pid_t chld)
{
	siginfo_t si;
	if (waitid(P_PID, chld, &si, WEXITED|WSTOPPED) != 0)
		err(1, "waitid");
	if (si.si_pid != chld)
		errx(1, "got unexpected pid in event\n");
	if (si.si_code != CLD_TRAPPED)
		errx(1, "got unexpected event type %d\n", si.si_code);
	return si;
}
static int
exec_and_report_test(const struct weston_test *t, void *test_data, int iteration)
{
	int success = 0;
	int skip = 0;
	int hardfail = 0;
	siginfo_t info;

	pid_t pid = fork();
	assert(pid >= 0);

	if (pid == 0)
		run_test(t, test_data); /* never returns */

	if (waitid(P_ALL, 0, &info, WEXITED)) {
		fprintf(stderr, "waitid failed: %m\n");
		abort();
	}

	if (test_data)
		fprintf(stderr, "test \"%s/%i\":\t", t->name, iteration);
	else
		fprintf(stderr, "test \"%s\":\t", t->name);

	switch (info.si_code) {
	case CLD_EXITED:
		fprintf(stderr, "exit status %d", info.si_status);
		if (info.si_status == EXIT_SUCCESS)
			success = 1;
		else if (info.si_status == SKIP)
			skip = 1;
		break;
	case CLD_KILLED:
	case CLD_DUMPED:
		fprintf(stderr, "signal %d", info.si_status);
		if (info.si_status != SIGABRT)
			hardfail = 1;
		break;
	}

	if (t->must_fail)
		success = !success;

	if (success && !hardfail) {
		fprintf(stderr, ", pass.\n");
		return 1;
	} else if (skip) {
		fprintf(stderr, ", skip.\n");
		return SKIP;
	} else {
		fprintf(stderr, ", fail.\n");
		return 0;
	}
}
Exemple #13
0
int
waitsys(idtype_t idtype, id_t id, siginfo_t *infop, int options)
{
	int error;
	k_siginfo_t info;

	if (error = waitid(idtype, id, &info, options))
		return (set_errno(error));
	if (copyout(&info, infop, sizeof (k_siginfo_t)))
		return (set_errno(EFAULT));
	return (0);
}
Exemple #14
0
ATF_TC_BODY(waitid_options, tc)
{
	size_t i = 0;
	int o;

	while((o = get_options6(i++)) != -1) {
		printf("Testing waitid(2) with options %x\n", o);

		ATF_REQUIRE_ERRNO(ECHILD,
		    waitid(P_ALL, 0, NULL, o | TWAIT_OPTION) == -1);
	}
}
Exemple #15
0
void
impl_exit_check(void)
{
    if( is_exiting == TRUE && total_tracked == 0 )
    {
        if( wait_mode == TRUE )
        {
            /* Check for any active child processes.
             * NOTE: Because we are using waitid() here, and
             * that allows us to specify WNOWAIT, the child
             * will stay in a waitable state for to be reaped
             * whenever the actual program wants to. */
            do {
                siginfo_t info;
                int rval = waitid(P_ALL, 0, &info, WNOHANG|WNOWAIT);
                if( rval < 0 && errno == EINTR )
                {
                    continue;
                }
                if( rval >= 0 || (rval < 0 && errno != ECHILD) )
                {
                    /* There are still active child processes. */
                    return;
                }
                break;
            } while( 1 );
        }

        DEBUG("No active connections, finishing exit.");

        switch( exit_strategy )
        {
            case FORK:
                /* We're done.
                 * No more connections are active, and there's
                 * presumably already a child process handling 
                 * new incoming connections. */
                DEBUG("Goodbye!");
                libc.exit(0);
                break;

            case EXEC:
                /* Let's do the exec.
                 * We're wrapped up existing connections, we can
                 * re-execute the application to start handling new
                 * incoming connections. */
                DEBUG("See you soon...");
                impl_exec();
                break;
        }
    }
}
int
main(void)
{
    pid_t pid;
    int a = 1;
    siginfo_t infop;

    if ((pid = fork()) < 0) {
        err_msg("fork error\n");
    } else if (0 == pid) {
        exit(7);
    }
    if (waitid(P_PID, pid, &infop, WEXITED) < 0) {
        err_msg("waitid error\n");
    }
    pr_exit(infop);

    if ((pid = fork()) < 0) {
        err_msg("fork error\n");
    } else if (0 == pid) {
        abort();
    }
    if (waitid(P_PID, pid, &infop, WEXITED) < 0) {
        err_msg("waitid error\n");
    }
    pr_exit(infop);

    if ((pid = fork()) < 0) {
        err_msg("fork error\n");
    } else if (0 == pid) {
        a /= 0;
    }
    if (waitid(P_PID, pid, &infop, WEXITED) < 0) {
        err_msg("waitid error\n");
    }
    pr_exit(infop);

    exit(0);
}
Exemple #17
0
static int signal_handler(int fd, uint32_t events, void *data,
			  struct lxc_epoll_descr *descr)
{
	struct signalfd_siginfo siginfo;
	siginfo_t info;
	int ret;
	pid_t *pid = data;
	bool init_died = false;

	ret = read(fd, &siginfo, sizeof(siginfo));
	if (ret < 0) {
		ERROR("Failed to read signal info from signal file descriptor: %d.", fd);
		return -1;
	}

	if (ret != sizeof(siginfo)) {
		ERROR("Unexpected size for siginfo struct.");
		return -1;
	}

	/* Check whether init is running. */
	info.si_pid = 0;
	ret = waitid(P_PID, *pid, &info, WEXITED | WNOWAIT | WNOHANG);
	if (ret == 0 && info.si_pid == *pid)
		init_died = true;

	if (siginfo.ssi_signo != SIGCHLD) {
		kill(*pid, siginfo.ssi_signo);
		INFO("Forwarded signal %d to pid %d.", siginfo.ssi_signo, *pid);
		return init_died ? 1 : 0;
	}

	if (siginfo.ssi_code == CLD_STOPPED) {
		INFO("Container init process was stopped.");
		return init_died ? 1 : 0;
	} else if (siginfo.ssi_code == CLD_CONTINUED) {
		INFO("Container init process was continued.");
		return init_died ? 1 : 0;
	}

	/* More robustness, protect ourself from a SIGCHLD sent
	 * by a process different from the container init.
	 */
	if (siginfo.ssi_pid != *pid) {
		WARN("Invalid pid for SIGCHLD. Received pid %d, expected pid %d.", siginfo.ssi_pid, *pid);
		return init_died ? 1 : 0;
	}

	DEBUG("Container init process %d exited.", *pid);
	return 1;
}
Exemple #18
0
int
waitsys32(idtype_t idtype, id_t id, siginfo_t *infop, int options)
{
	int error;
	k_siginfo_t info;
	siginfo32_t info32;

	if (error = waitid(idtype, id, &info, options))
		return (set_errno(error));
	siginfo_kto32(&info, &info32);
	if (copyout(&info32, infop, sizeof (info32)))
		return (set_errno(EFAULT));
	return (0);
}
Exemple #19
0
static int signal_handler(int fd, uint32_t events, void *data,
			   struct lxc_epoll_descr *descr)
{
	struct signalfd_siginfo siginfo;
	siginfo_t info;
	int ret;
	pid_t *pid = data;
	bool init_died = false;

	ret = read(fd, &siginfo, sizeof(siginfo));
	if (ret < 0) {
		ERROR("failed to read signal info");
		return -1;
	}

	if (ret != sizeof(siginfo)) {
		ERROR("unexpected siginfo size");
		return -1;
	}

	// check whether init is running
	info.si_pid = 0;
	ret = waitid(P_PID, *pid, &info, WEXITED | WNOWAIT | WNOHANG);
	if (ret == 0 && info.si_pid == *pid) {
		init_died = true;
	}

	if (siginfo.ssi_signo != SIGCHLD) {
		kill(*pid, siginfo.ssi_signo);
		INFO("forwarded signal %d to pid %d", siginfo.ssi_signo, *pid);
		return init_died ? 1 : 0;
	}

	if (siginfo.ssi_code == CLD_STOPPED ||
	    siginfo.ssi_code == CLD_CONTINUED) {
		INFO("container init process was stopped/continued");
		return init_died ? 1 : 0;
	}

	/* more robustness, protect ourself from a SIGCHLD sent
	 * by a process different from the container init
	 */
	if (siginfo.ssi_pid != *pid) {
		WARN("invalid pid for SIGCHLD");
		return init_died ? 1 : 0;
	}

	DEBUG("container init process exited");
	return 1;
}
Exemple #20
0
bool
app_launcher::update_status(bool wait)
{
    if (m_status_code != STATUS_RUNNING)
        return false;

    assert(m_child_pid >= 0);

    int options = WEXITED; // WSTOPPED: wait for children stopped by delivery of signal.
    if(!wait)
        options |= WNOHANG;

    siginfo_t signalinfo;
    int ret = waitid(P_PID, m_child_pid, &signalinfo, options);

    if (ret == -1)
    {
        m_status_code = STATUS_ERROR;
        m_status = ret;
        assert(0);
        return false;
    }
    else
    {
        // If we ever care about signals and whatnot:
        //  signalinfo.si_signo;    // Signal number.
        //  signalinfo.si_code;     // Signal code: CLD_EXITED, CLD_DUMPED, CLD_KILLED.
        //  signalinfo.si_errno;    // Error number associated with signal.
        //  signalinfo.si_status;   // Exit value.
        switch(signalinfo.si_code)
        {
        default:
            assert(0);
        case CLD_EXITED:
            m_status_code = STATUS_EXITED;
            m_status = signalinfo.si_status;
            break;
        case CLD_KILLED:
            m_status_code = STATUS_KILLED;
            m_status = 0;
            break;
        case CLD_DUMPED:
            m_status_code = STATUS_DUMPED;
            m_status = 0;
            break;
        }
    }

    return true;
}
Exemple #21
0
int wait_for_child(int options) {
	id_t id_ignored = 0;
	siginfo_t infop;

	infop.si_pid = 0;
	waitid(P_ALL, id_ignored, &infop, WEXITED | options);
	if (infop.si_pid == 0) {
		return -1; /* Nothing to wait for */
	}
	if (infop.si_code == CLD_EXITED) {
		return infop.si_status;
	}
	return 1;
}
bool FProcState::IsRunning()
{
	if (bIsRunning)
	{
		check(!bHasBeenWaitedFor);	// check for the sake of internal consistency

		// check if actually running
		int KillResult = kill(GetProcessId(), 0);	// no actual signal is sent
		check(KillResult != -1 || errno != EINVAL);

		bIsRunning = (KillResult == 0 || (KillResult == -1 && errno == EPERM));

		// additional check if it's a zombie
		if (bIsRunning)
		{
			for(;;)	// infinite loop in case we get EINTR and have to repeat
			{
				siginfo_t SignalInfo;
				SignalInfo.si_pid = 0;	// if remains 0, treat as child was not waitable (i.e. was running)
				if (waitid(P_PID, GetProcessId(), &SignalInfo, WEXITED | WNOHANG | WNOWAIT))
				{
					if (errno != EINTR)
					{
						int ErrNo = errno;
						UE_LOG(LogHAL, Fatal, TEXT("FLinuxPlatformProcess::WaitForProc: waitid for pid %d failed (errno=%d, %s)"), 
							static_cast< int32 >(GetProcessId()), ErrNo, ANSI_TO_TCHAR(strerror(ErrNo)));
						break;	// exit the loop if for some reason Fatal log (above) returns
					}
				}
				else
				{
					bIsRunning = ( SignalInfo.si_pid != GetProcessId() );
					break;
				}
			}
		}

		// If child is a zombie, wait() immediately to free up kernel resources. Higher level code
		// (e.g. shader compiling manager) can hold on to handle of no longer running process for longer,
		// which is a dubious, but valid behavior. We don't want to keep zombie around though.
		if (!bIsRunning)
		{
			UE_LOG(LogHAL, Log, TEXT("Child %d is no more running (zombie), Wait()ing immediately."), GetProcessId() );
			Wait();
		}
	}

	return bIsRunning;
}
Exemple #23
0
/*Checa se ha job terminado no ultimo contexto, imprimindo e liberando espaco*/
void checkjob(){
    siginfo_t signal;
    int i;
    for(i = 1; i < MAX_JOBS ; i++) {
        signal.si_pid = 0;
        if (!(!waitid(P_PID ,jobs[i].p_id, &signal, WNOHANG | WEXITED)) && signal.si_pid == 0){
            if (jobs[i].flag != 0){
                printf("[%d]\t", i);
                printf("Terminado\t");
                printf("%s \n",jobs[i].p_name);
                jobs[i].flag = 0;
            }
        }
    }
}
Exemple #24
0
/*Imprime jobs em background*/
void imprimejob(){
    siginfo_t signal;
    int i;
    for(i = 1; i < MAX_JOBS ; i++) {
        if ((jobs[i].flag == 0) || (jobs[i].flag == 2)) continue;
        signal.si_pid = 0;
        if ((!waitid(P_PID ,jobs[i].p_id, &signal, WNOHANG | WEXITED)) && signal.si_pid == 0){
            if (jobs[i].flag !=3) jobs[i].flag = 1;
            printf("[%d]\t", jobs[i].p_id);
            printf("%%%d\t", jobs[i].j_id);
            printf("%s\t", jobs[i].p_status);
            printf("%s &\n",jobs[i].p_name);
        }
        else jobs[i].flag = 2;
    }
}
Exemple #25
0
void child_t::sigchld_handler(int sig) {
	siginfo_t siginfo;
	char line[MAX_PACKETLEN]={0};
	fprintf(stderr, "parent: received signal %d.\n", sig);

	siginfo.si_pid=0;					// get wait info
	if ( waitid(P_ALL, 0, &siginfo, WEXITED | WSTOPPED | WCONTINUED | WNOHANG) < 0 ) {
		perror("wait failed");
	}
	if ( siginfo.si_pid == 0 ) {
		printf("warning: wait returned siginfo.si_pid==0.\n");
		return;
	}

	child_t* child = child_t::findbyPID(siginfo.si_pid);	// find corresponding child
	if ( child == NULL ) {
		printf("warning: received SIGCHLD from (pid %d), which is no child!\n", siginfo.si_pid);
		child_t::ListChildren();
		return;
	}

	// update child status
	child->status = siginfo.si_code;
	child->pid = (pid_t)-1;
	line[0]=0;	// clear line				// compose info message
	lineadd(line, "%s > status=%s",  child->clientid, child->ChildStatusString() );
	//lineadd(line, "FIXME > status=%s",  child->ChildStatusString() );	// FIXME: no clientid here
	lineadd(line, ", pid=%d", siginfo.si_pid);
	lineadd(line, ", uid=%d", siginfo.si_uid);
	if (WIFSIGNALED(siginfo.si_status)) {
		lineadd(line, ", termsig=%d", WTERMSIG(siginfo.si_status));
#		ifdef WCOREDUMP
		lineadd(line, ", coredump=%s", WCOREDUMP(siginfo.si_status)?"true":"false");
#		endif
	}
	if (WIFSTOPPED(siginfo.si_status) ) {
		lineadd(line, ", stopsig=%d", WSTOPSIG(siginfo.si_status));
	}
	if (WIFEXITED(siginfo.si_status) ) {
		lineadd(line, ", return_status=%d", WEXITSTATUS(siginfo.si_status));
	}
	if ( meptr != NULL ) {
		(meptr)->printf("%ld %s\n", time(NULL), line);
	} else {
		printf("%s\n", line);
	}
}
Exemple #26
0
// Block until child_pid exits, then exit. Try to preserve the exit code.
static void WaitForChildAndExit(pid_t child_pid) {
  int exit_code = -1;
  siginfo_t reaped_child_info;

  int wait_ret =
    HANDLE_EINTR(waitid(P_PID, child_pid, &reaped_child_info, WEXITED));

  if (!wait_ret && reaped_child_info.si_pid == child_pid) {
    if (reaped_child_info.si_code == CLD_EXITED) {
      exit_code = reaped_child_info.si_status;
    } else {
      // Exit with code 0 if the child got signaled.
      exit_code = 0;
    }
  }
  _exit(exit_code);
}
Exemple #27
0
/** Starts the web100srv process. Either args must be NULL or the last element
 *  of **args must be NULL. */
pid_t start_server(int port, char **extra_args) {
  int extra_args_index = 0;
  char *arg;
  pid_t server_pid;
  siginfo_t server_status;
  char port_string[6];  // 32767 is the max port, so must hold 5 digits + \0
  int rv;
  char *args_for_exec[256] = {"./web100srv", "--snaplog", "--tcpdump",
    "--cputime", "--log_dir", "/tmp", "-l", LOGFILE_TEMPLATE, "--port", NULL};
  int exec_args_index = 0;
  // set exec_args_index to the first index of args_for_exec that is NULL
  while (args_for_exec[exec_args_index] != NULL) {
    // along the way, fill in the template for the test logs
    if (strcmp(args_for_exec[exec_args_index], LOGFILE_TEMPLATE) == 0) {
      mkstemp(args_for_exec[exec_args_index]);
    }
    exec_args_index++;
  }
  log_println(1, "Starting the server");
  if ((server_pid = fork()) == 0) {
    sprintf(port_string, "%d", port);
    args_for_exec[exec_args_index++] = port_string;
    while (extra_args != NULL && extra_args[extra_args_index] != NULL) {
      CHECK((args_for_exec[exec_args_index++] =
             strdup(extra_args[extra_args_index++])) != NULL);
    }
    args_for_exec[exec_args_index++] = NULL;
    execv("./web100srv", args_for_exec);
    perror("SERVER START ERROR: SHOULD NEVER HAPPEN");
    FAIL("The server should never return - it should only be killed.");
    exit(1);
  }
  // Wait until the server port (hopefully) becomes available. The server PID is
  // available immediately, but we need to make sure to lose the race condition
  // with the server startup process, so that the NDT port is open and ready to
  // receive traffic and we won't begin the test before the server's startup
  // routines are complete.
  sleep(1);
  // Double-check that the server didn't crash on startup.
  server_status.si_pid = 0;
  rv = waitid(P_PID, server_pid, &server_status, WEXITED | WSTOPPED | WNOHANG);
  ASSERT(rv == 0 && server_status.si_pid == 0,
         "The server did not start successfully (exit code %d)", rv);
  return server_pid;
}
Exemple #28
0
int
main(void)
{
	void *buf;
	pid_t child;
	int ret, i;
	siginfo_t info;
	uint8_t *ubuf;
	size_t mapsz = sysconf(_SC_PAGESIZE) * 2;

	buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE,
	    MAP_PRIVATE | MAP_ANON, -1, 0);
	assert(buf != MAP_FAILED);

	ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0);
	assert(ret == 0);

again:
	memset(buf, 'a' + nchild, mapsz);
	child = fork();
	if (child == 0) {
		nchild--;
		for (i = 0, ubuf = buf; i < mapsz; i++)
			assert(ubuf[i] == 0);
		if (nchild != 0)
			goto again;
		exit(0);
	}
	assert(child != -1);

	do {
		ret = waitid(P_PID, child, &info, WEXITED);
	} while (ret == -1 && errno == EINTR);
	assert(ret == 0);
	assert(info.si_pid == child);
	assert(info.si_status == 0);

	for (i = 0, ubuf = buf; i < mapsz; i++)
		assert(ubuf[i] == 'a' + nchild);

	return (0);
}
Exemple #29
0
static int manager_signal_fn(sd_event_source *source,
			     const struct signalfd_siginfo *ssi,
			     void *data)
{
	struct manager *m = data;

	if (ssi->ssi_signo == SIGCHLD) {
		log_debug("caught SIGCHLD for %ld, reaping child", (long)ssi->ssi_pid);
		waitid(P_PID, ssi->ssi_pid, NULL, WNOHANG|WEXITED);
		return 0;
	} else if (ssi->ssi_signo == SIGPIPE) {
		/* ignore SIGPIPE */
		return 0;
	}

	log_notice("caught signal %d, exiting..", (int)ssi->ssi_signo);
	sd_event_exit(m->event, 0);

	return 0;
}
Exemple #30
0
int main(void) {
  int i = 0;
  pid_t pid;
  int status;
  siginfo_t si;

  ++i;
  pid = fork();
  if (!pid) {
    usleep(100);
    exit(i);
  }
  test_assert(pid == wait(&status));
  atomic_printf("%d exited with status %#x\n", pid, status);
  test_assert(WIFEXITED(status) && i == WEXITSTATUS(status));

  ++i;
  pid = fork();
  if (!pid) {
    usleep(100);
    exit(i);
  }
  test_assert(pid == waitpid(pid, &status, 0));
  atomic_printf("%d exited with status %#x\n", pid, status);
  test_assert(WIFEXITED(status) && i == WEXITSTATUS(status));

  ++i;
  pid = fork();
  if (!pid) {
    usleep(100);
    exit(i);
  }
  test_assert(0 == waitid(P_PID, pid, &si, WEXITED | WSTOPPED));
  atomic_printf("%d exited with exit-type %d; code %d\n", si.si_pid, si.si_code,
                si.si_status);
  test_assert(SIGCHLD == si.si_signo && CLD_EXITED == si.si_code);
  test_assert(pid == si.si_pid && i == si.si_status);

  atomic_puts("EXIT-SUCCESS");
  return 0;
}