Beispiel #1
0
static void do_child_1(void)
{
	pid_t pid, group;
	int i;

	group = SAFE_GETPGID(0);

	for (i = 0; i < MAXKIDS; i++) {
		if (i == (MAXKIDS / 2))
			SAFE_SETPGID(0, 0);

		pid = SAFE_FORK();
		if (pid == 0)
			do_exit(0);

		fork_kid_pid[i] = pid;
	}

	TST_CHECKPOINT_WAKE2(0, MAXKIDS);

	if (reap_children(0, 0, fork_kid_pid + (MAXKIDS / 2), MAXKIDS / 2))
		return;

	/* Make sure can pickup children in a diff. process group */
	if (reap_children(-group, 0, fork_kid_pid, MAXKIDS / 2))
		return;

	tst_res(TPASS, "Test PASSED");
}
Beispiel #2
0
static void run_tests(void)
{
	unsigned int i;
	struct results saved_results;

	if (!tst_test->test) {
		saved_results = *results;
		tst_test->test_all();

		if (getpid() != main_pid) {
			exit(0);
		}

		reap_children();

		if (results_equal(&saved_results, results))
			tst_brk(TBROK, "Test haven't reported results!");
		return;
	}

	for (i = 0; i < tst_test->tcnt; i++) {
		saved_results = *results;
		tst_test->test(i);

		if (getpid() != main_pid) {
			exit(0);
		}

		reap_children();

		if (results_equal(&saved_results, results))
			tst_brk(TBROK, "Test %i haven't reported results!", i);
	}
}
Beispiel #3
0
void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret,
                        apr_pool_t *p)
{
    apr_status_t rv;

    ++wait_or_timeout_counter;
    if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
        wait_or_timeout_counter = 0;
        ap_run_monitor(p);
    }

    rv = apr_proc_wait_all_procs(ret, exitcode, status, APR_NOWAIT, p);
    if (APR_STATUS_IS_EINTR(rv)) {
        ret->pid = -1;
        return;
    }

    if (APR_STATUS_IS_CHILD_DONE(rv)) {
        return;
    }

#ifdef NEED_WAITPID
    if ((ret = reap_children(exitcode, status)) > 0) {
        return;
    }
#endif

    apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL);
    ret->pid = -1;
    return;
}
Beispiel #4
0
/** Restart the server with a message.
 * @param[in] message Message to log and send to operators.
 */
void server_restart(const char *message)
{
  static int restarting = 0;

  /* inhibit sending any server notices; we may be in a loop */
  log_write(LS_SYSTEM, L_WARNING, LOG_NOSNOTICE, "Restarting Server: %s",
	    message);
  if (restarting++) /* increment restarting to prevent looping */
    return;

  sendto_opmask_butone(0, SNO_OLDSNO, "Restarting server: %s", message);
  Debug((DEBUG_NOTICE, "Restarting server..."));
  flush_connections(0);

  log_close();

  close_connections(!(thisServer.bootopt & (BOOT_TTY | BOOT_DEBUG | BOOT_CHKCONF)));

  reap_children();

  execv(SPATH, thisServer.argv);

  /* Have to reopen since it has been closed above */
  log_reopen();

  log_write(LS_SYSTEM, L_CRIT, 0, "execv(%s,%s) failed: %m", SPATH,
	    *thisServer.argv);

  Debug((DEBUG_FATAL, "Couldn't restart server \"%s\": %s",
         SPATH, (strerror(errno)) ? strerror(errno) : ""));
  exit(8);
}
Beispiel #5
0
static void do_child_1(void)
{
	pid_t pid;
	int i;

	for (i = 0; i < MAXKIDS; i++) {
		pid = SAFE_FORK();
		if (pid == 0) {
			if (i == 0 || i == 1)
				do_exit(0);

			if (i == 2 || i == 3)
				do_compute();

			if (i == 4 || i == 5)
				do_fork();

			if (i == 6 || i == 7)
				do_sleep();
		}

		fork_kid_pid[i] = pid;
	}

	TST_CHECKPOINT_WAKE2(0, MAXKIDS);

	if (TST_TRACE(reap_children(0, 0, fork_kid_pid, MAXKIDS)))
		return;

	tst_res(TPASS, "Test PASSED");
}
int main()
{
    fd_set rdset, wrset;
    int max;
    sigset_t chld_set;

    init();
    signal(SIGCHLD, sigchld_handler);
    signal(SIGPIPE, SIG_IGN);
    sigemptyset(&chld_set);
    sigaddset(&chld_set, SIGCHLD);


    for (;;) {
        sigprocmask(SIG_BLOCK, &chld_set, NULL);
        if (child_exited)
            reap_children();
        max = fill_fds_for_select(&rdset, &wrset);
        if (libvchan_buffer_space(ctrl_vchan) <=
                (int)sizeof(struct msg_header))
            FD_ZERO(&rdset);

        wait_for_vchan_or_argfd(ctrl_vchan, max, &rdset, &wrset);
        sigprocmask(SIG_UNBLOCK, &chld_set, NULL);

        while (libvchan_data_ready(ctrl_vchan))
            handle_server_cmd();

        if (FD_ISSET(trigger_fd, &rdset))
            handle_trigger_io();

        handle_terminated_fork_client(&rdset);
    }
}
int main(int argc, char **argv)
{
    fd_set read_fdset, write_fdset;
    int i, opt;
    int max;
    sigset_t chld_set;

    while ((opt=getopt(argc, argv, "q")) != -1) {
        switch (opt) {
            case 'q':
                opt_quiet = 1;
                break;
            default: /* '?' */
                fprintf(stderr, "usage: %s [-q] domainid domain-name [default user]\n", argv[0]);
                exit(1);
        }
    }
    if (argc - optind < 2 || argc - optind > 3) {
        fprintf(stderr, "usage: %s [-q] domainid domain-name [default user]\n", argv[0]);
        exit(1);
    }
    remote_domain_id = atoi(argv[optind]);
    remote_domain_name = argv[optind+1];
    if (argc - optind >= 3)
        default_user = argv[optind+2];
    init(remote_domain_id);
    sigemptyset(&chld_set);
    sigaddset(&chld_set, SIGCHLD);
    signal(SIGCHLD, sigchld_handler);
    /*
     * The main event loop. Waits for one of the following events:
     * - message from client
     * - message from agent
     * - new client
     * - child exited
     */
    for (;;) {
        max = fill_fdsets_for_select(&read_fdset, &write_fdset);
        if (libvchan_buffer_space(vchan) <= (int)sizeof(struct msg_header))
            FD_ZERO(&read_fdset);	// vchan full - don't read from clients

        sigprocmask(SIG_BLOCK, &chld_set, NULL);
        if (child_exited)
            reap_children();
        wait_for_vchan_or_argfd(vchan, max, &read_fdset, &write_fdset);
        sigprocmask(SIG_UNBLOCK, &chld_set, NULL);

        if (FD_ISSET(qrexec_daemon_unix_socket_fd, &read_fdset))
            handle_new_client();

        while (libvchan_data_ready(vchan))
            handle_message_from_agent();

        for (i = 0; i <= max_client_fd; i++)
            if (clients[i].state != CLIENT_INVALID
                && FD_ISSET(i, &read_fdset))
                handle_message_from_client(i);
    }
}
Beispiel #8
0
int main(int argc, char **argv)
{
	fd_set read_fdset, write_fdset;
	int i;
	int max;
	sigset_t chld_set;

	if (argc != 2) {
		fprintf(stderr, "usage: %s domainid\n", argv[0]);
		exit(1);
	}
	init(atoi(argv[1]));
	sigemptyset(&chld_set);
	sigaddset(&chld_set, SIGCHLD);
	/*
	   The main event loop. Waits for one of the following events:
	   - message from client
	   - message from agent
	   - new client
	   - child exited
	 */
	for (;;) {
		max = fill_fdsets_for_select(&read_fdset, &write_fdset);
		if (buffer_space_vchan_ext() <=
		    sizeof(struct server_header))
			FD_ZERO(&read_fdset);	// vchan full - don't read from clients

		sigprocmask(SIG_BLOCK, &chld_set, NULL);
		if (child_exited)
			reap_children();
		wait_for_vchan_or_argfd(max, &read_fdset, &write_fdset);
		sigprocmask(SIG_UNBLOCK, &chld_set, NULL);

		if (FD_ISSET(qrexec_daemon_unix_socket_fd, &read_fdset))
			handle_new_client();

		while (read_ready_vchan_ext())
			handle_message_from_agent();

		for (i = 0; i <= max_client_fd; i++)
			if (clients[i].state != CLIENT_INVALID
			    && FD_ISSET(i, &read_fdset))
				handle_message_from_client(i);

		for (i = 0; i <= max_client_fd; i++)
			if (clients[i].state != CLIENT_INVALID
			    && FD_ISSET(i, &write_fdset))
				write_buffered_data_to_client(i);

	}
}
Beispiel #9
0
static void do_child_1(void)
{
	pid_t pid, group;
	int i;
	int status;

	group = SAFE_GETPGID(0);

	for (i = 0; i < MAXKIDS; i++) {
		if (i == (MAXKIDS / 2))
			SAFE_SETPGID(0, 0);

		pid = SAFE_FORK();
		if (pid == 0)
			do_exit(0);

		fork_kid_pid[i] = pid;
	}

	if (TST_TRACE(waitpid_ret_test(0, &status, WNOHANG, 0, 0)))
		return;

	if (TST_TRACE(waitpid_ret_test(-group, &status, WNOHANG, 0, 0)))
		return;

	TST_CHECKPOINT_WAKE2(0, MAXKIDS);

	if (TST_TRACE(reap_children(0, WNOHANG, fork_kid_pid + (MAXKIDS / 2),
				    MAXKIDS / 2)))
		return;

	if (TST_TRACE(reap_children(-group, WNOHANG, fork_kid_pid,
				    MAXKIDS / 2)))
		return;

	tst_res(TPASS, "Test PASSED");
}
Beispiel #10
0
int main(int argc, char **argv)
{
	if (argc < 2)
		help();

	/* Get number of processes to use */
	num_sorts = atoi(argv[1]);

	if (num_sorts > 1000)
		printf("Number of sorts is OVER 9000!!!\n");

	/* Setup signal handlers */
	struct sigaction act;

	act.sa_handler = grim_reaper;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;

	sigaction(SIGQUIT, &act, NULL);
	sigaction(SIGINT, &act, NULL);
	sigaction(SIGHUP, &act, NULL);

	/* Generate all necessary pipes for sort */
	sortpipefds = generate_pipes_array(num_sorts);

	/* Generate pipes for the suppressor */
	suppipefds = generate_pipes_array(num_sorts);

	/* Spawn sort processes */
	spawn_sorts(sortpipefds, suppipefds);

	/* Parse STDIN */
	r_r_parser(sortpipefds);

	/* Spawn suppressor process */
	spawn_suppressor(suppipefds);

	/* Wait for child processes to die */
	reap_children(num_sorts);

	/* Free malloced arrays of pipes */
	free_pipes_array(num_sorts, sortpipefds);
	free_pipes_array(num_sorts, suppipefds);
	free(process_array);
	return (0);
}
Beispiel #11
0
static void do_fork(void)
{
	pid_t fork_pid;
	int i;

	TST_CHECKPOINT_WAIT(0);

	for (i = 0; i < 50; i++) {
		fork_pid = SAFE_FORK();
		if (fork_pid == 0)
			exit(3);

		if (TST_TRACE(reap_children(fork_pid, 0, &fork_pid, 1)))
			break;
	}

	exit(3);
}
Beispiel #12
0
/*
 *	Thread wrapper for fork().
 */
pid_t rad_fork(void)
{
	pid_t child_pid;

	if (!pool_initialized) return fork();

	reap_children();	/* be nice to non-wait thingies */

	if (fr_hash_table_num_elements(thread_pool.waiters) >= 1024) {
		return -1;
	}

	/*
	 *	Fork & save the PID for later reaping.
	 */
	child_pid = fork();
	if (child_pid > 0) {
		int rcode;
		thread_fork_t *tf;

		tf = rad_malloc(sizeof(*tf));
		memset(tf, 0, sizeof(*tf));

		tf->pid = child_pid;

		pthread_mutex_lock(&thread_pool.wait_mutex);
		rcode = fr_hash_table_insert(thread_pool.waiters, tf);
		pthread_mutex_unlock(&thread_pool.wait_mutex);

		if (!rcode) {
			radlog(L_ERR, "Failed to store PID, creating what will be a zombie process %d",
			       (int) child_pid);
			free(tf);
		}
	}

	/*
	 *	Return whatever we were told.
	 */
	return child_pid;
}
int main(int argc, char **argv)
{
    int fd;
    int i;
    pid_t pid;
    sigset_t set;

    mainParseOptions(argc, argv);
    printf("yang test ... opt_send_signal:%d\r\n", opt_send_signal);
    if (-1 == opt_send_signal)
        if (checkRunningPid())
            exit(1);

    enableCoredumps();
    writePidFile();
    save_argv(argc, argv);
    init_setproctitle();
    init_signals();
    sigemptyset(&set);

    printf("father pid1=%d\n",getpid());
    int worker_processes = 3;
    start_worker_processes(worker_processes, PROCESS_RESPAWN);

    start_dispatcher_process(PROCESS_RESPAWN);
    printf("father pid2=%d\n", getpid());

    setproctitle("nginx:master");
    int live = 1;
    for (;;) {
        printf("father before suspend\n");
        sigsuspend(&set);
        printf("father after suspend\n");
        if (reap) {
            reap = 0;             
            fprintf(stderr, "reap children\n");
            live = reap_children();
        }
    }
    return 0;
}
Beispiel #14
0
/*
 *	Wait 10 seconds at most for a child to exit, then give up.
 */
pid_t rad_waitpid(pid_t pid, int *status)
{
	int i;
	thread_fork_t mytf, *tf;

	if (!pool_initialized) return waitpid(pid, status, 0);

	if (pid <= 0) return -1;

	mytf.pid = pid;

	pthread_mutex_lock(&thread_pool.wait_mutex);
	tf = fr_hash_table_finddata(thread_pool.waiters, &mytf);
	pthread_mutex_unlock(&thread_pool.wait_mutex);

	if (!tf) return -1;

	for (i = 0; i < 100; i++) {
		reap_children();

		if (tf->exited) {
			*status = tf->status;

			pthread_mutex_lock(&thread_pool.wait_mutex);
			fr_hash_table_delete(thread_pool.waiters, &mytf);
			pthread_mutex_unlock(&thread_pool.wait_mutex);
			return pid;
		}
		usleep(100000);	/* sleep for 1/10 of a second */
	}

	/*
	 *	10 seconds have passed, give up on the child.
	 */
	pthread_mutex_lock(&thread_pool.wait_mutex);
	fr_hash_table_delete(thread_pool.waiters, &mytf);
	pthread_mutex_unlock(&thread_pool.wait_mutex);

	return 0;
}
Beispiel #15
0
/*
Signal Handler
Reference: http://stackoverflow.com/questions/1641182/how-can-i-catch-a-ctrl-c-event-c
*/
void grim_reaper(int s)
{
	int i;
	int kid_signal = 0; /* signal to send to children */
	switch(s){
		case SIGQUIT:
			kid_signal = SIGQUIT;
			break;
		case SIGHUP:
			kid_signal = SIGQUIT;
			break;
		case SIGINT:
			kid_signal = SIGINT;
			break;
		default:
			kid_signal = SIGQUIT;
	}

	/* Send signals to children */
	if (process_array != NULL) {
		for (i = 0; i < num_sorts; i++) {
			kill(process_array[i], kid_signal);
		}
	}
	/* Wait for child processes to die */
	reap_children(num_sorts);

	/* Free malloced arrays */
	if (sortpipefds != NULL)
		free_pipes_array(num_sorts, sortpipefds);
	if (suppipefds != NULL)
		free_pipes_array(num_sorts, suppipefds);
	free(process_array);
	
	exit(1);
}
Beispiel #16
0
void httpd_main(void)
{
	int rv, n, t, accepting;
	time_t hours, last_time;

	accepting = 1;
	last_time = current_time = startuptime = time(0);
	hours = current_time / 3600;
	log_d("*** %s starting", server_version);
	while (gotsigterm == 0) {
		if (gotsighup) {
			gotsighup = 0;
			init_logs(0);
			if (debug)
				log_d("logs reopened");
		}
		if (gotsigusr1) {
			gotsigusr1 = 0;
			close_connections();
			log_d("connections closed");
		}
		if (gotsigusr2) {
			gotsigusr2 = 0;
			close_servers();
			log_d("servers closed");
		}
		if (gotsigchld) {
			gotsigchld = 0;
			reap_children();
		}
		if (gotsigquit) {
			gotsigquit = 0;
			debug = debug == 0;
			if (debug)
				log_d("debugging turned on");
			else
				log_d("debugging turned off");
		}
		if (gotsigwinch) {
			gotsigwinch = 0;
			log_d("performing internal dump");
			internal_dump();
		}
		n = 0;
		if (accepting && find_connection())
			n = setup_server_pollfds(n);
		n = setup_connection_pollfds(n);
		n = setup_child_pollfds(n, forked_connections.head);
		if (n == 0 && accepting && stats.nconnections == 0) {
			log_d("no more sockets to poll from");
			break;
		}
		t = accepting ? 60000 : 1000;
		if (debug)
			dump_pollfds(n, 0);
		rv = poll(pollfds, n, t);
		current_time = time(0);
		if (rv == -1) {
			if (errno != EINTR) {
				lerror("poll");
				break;
			} else {
				if (debug)
					log_d("poll interrupted");
				continue;
			}
		}
		if (debug)
			dump_pollfds(n, 1);
		if (current_time != last_time) {
			if (accepting == 0)
				accepting = 1;
			if (current_time / 3600 != hours) {
				hours = current_time / 3600;
				init_logs(0);
				if (debug)
					log_d("logs rotated");
			}
		}
		if (rv) {
			if (accepting && run_servers() == -1)
				accepting = 0;
			run_connections();
		}
		if (current_time != last_time) {
			cleanup_connections();
			last_time = current_time;
		}
	}
	log_d("*** shutting down");
}
/*
 *	Remove a request from the queue.
 */
static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
{
	int blocked;
	RAD_LISTEN_TYPE i, start;
	request_queue_t *entry;

	reap_children();

	pthread_mutex_lock(&thread_pool.queue_mutex);

	/*
	 *	Clear old requests from all queues.
	 *
	 *	We only do one pass over the queue, in order to
	 *	amortize the work across the child threads.  Since we
	 *	do N checks for one request de-queued, the old
	 *	requests will be quickly cleared.
	 */
	for (i = 0; i < RAD_LISTEN_MAX; i++) {
		entry = fr_fifo_peek(thread_pool.fifo[i]);
		if (!entry ||
		    (entry->request->master_state != REQUEST_STOP_PROCESSING)) {
			continue;
}
		/*
		 *	This entry was marked to be stopped.  Acknowledge it.
		 */
		entry = fr_fifo_pop(thread_pool.fifo[i]);
		rad_assert(entry != NULL);
		entry->request->child_state = REQUEST_DONE;
		thread_pool.num_queued--;
		free(entry);
		entry = NULL;
	}

	start = 0;
 retry:
	/*
	 *	Pop results from the top of the queue
	 */
	for (i = start; i < RAD_LISTEN_MAX; i++) {
		entry = fr_fifo_pop(thread_pool.fifo[i]);
		if (entry) {
			start = i;
			break;
		}
	}

	if (!entry) {
		pthread_mutex_unlock(&thread_pool.queue_mutex);
		*request = NULL;
		*fun = NULL;
		return 0;
	}

	rad_assert(thread_pool.num_queued > 0);
	thread_pool.num_queued--;
	*request = entry->request;
	*fun = entry->fun;
	free(entry);
	entry = NULL;

	rad_assert(*request != NULL);
	rad_assert((*request)->magic == REQUEST_MAGIC);
	rad_assert(*fun != NULL);

	(*request)->component = "<core>";
	(*request)->module = "<thread>";

	/*
	 *	If the request has sat in the queue for too long,
	 *	kill it.
	 *
	 *	The main clean-up code can't delete the request from
	 *	the queue, and therefore won't clean it up until we
	 *	have acknowledged it as "done".
	 */
	if ((*request)->master_state == REQUEST_STOP_PROCESSING) {
		(*request)->module = "<done>";
		(*request)->child_state = REQUEST_DONE;
		goto retry;
	}

	/*
	 *	Produce messages for people who have 10 million rows
	 *	in a database, without indexes.
	 */
	rad_assert(almost_now != 0);
	blocked = almost_now - (*request)->timestamp;
	if (blocked < 5) {
		blocked = 0;
	} else {
		static time_t last_complained = 0;
		
		if (last_complained != almost_now) {
			last_complained = almost_now;
		} else {
			blocked = 0;
		}
	}

	/*
	 *	The thread is currently processing a request.
	 */
	thread_pool.active_threads++;

	pthread_mutex_unlock(&thread_pool.queue_mutex);

	if (blocked) {
		radlog(L_ERR, "Request %u has been waiting in the processing queue for %d seconds.  Check that all databases are running properly!",
		       (*request)->number, blocked);
	}

	return 1;
}
Beispiel #18
0
int
update_goal_chain (struct dep *goals)
{
  int t = touch_flag, q = question_flag, n = just_print_flag;
  int status = -1;

#define	MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \
		     : file_mtime (file))

  /* Duplicate the chain so we can remove things from it.  */

  goals = copy_dep_chain (goals);

  {
    /* Clear the 'changed' flag of each goal in the chain.
       We will use the flag below to notice when any commands
       have actually been run for a target.  When no commands
       have been run, we give an "up to date" diagnostic.  */

    struct dep *g;
    for (g = goals; g != 0; g = g->next)
      g->changed = 0;
  }

  /* All files start with the considered bit 0, so the global value is 1.  */
  considered = 1;

  /* Update all the goals until they are all finished.  */

  while (goals != 0)
    {
      register struct dep *g, *lastgoal;

      /* Start jobs that are waiting for the load to go down.  */

      start_waiting_jobs ();

      /* Wait for a child to die.  */

      reap_children (1, 0);

      lastgoal = 0;
      g = goals;
      while (g != 0)
	{
	  /* Iterate over all double-colon entries for this file.  */
	  struct file *file;
	  int stop = 0, any_not_updated = 0;

	  for (file = g->file->double_colon ? g->file->double_colon : g->file;
	       file != NULL;
	       file = file->prev)
	    {
	      unsigned int ocommands_started;
	      int x;

              file->dontcare = g->dontcare;

	      check_renamed (file);
	      if (rebuilding_makefiles)
		{
		  if (file->cmd_target)
		    {
		      touch_flag = t;
		      question_flag = q;
		      just_print_flag = n;
		    }
		  else
		    touch_flag = question_flag = just_print_flag = 0;
		}

	      /* Save the old value of 'commands_started' so we can compare
		 later.  It will be incremented when any commands are
		 actually run.  */
	      ocommands_started = commands_started;

	      x = update_file (file, rebuilding_makefiles ? 1 : 0);
	      check_renamed (file);

	      /* Set the goal's 'changed' flag if any commands were started
		 by calling update_file above.  We check this flag below to
		 decide when to give an "up to date" diagnostic.  */
              if (commands_started > ocommands_started)
                g->changed = 1;

              /* If we updated a file and STATUS was not already 1, set it to
                 1 if updating failed, or to 0 if updating succeeded.  Leave
                 STATUS as it is if no updating was done.  */

	      stop = 0;
	      if ((x != 0 || file->updated) && status < 1)
                {
                  if (file->update_status != 0)
                    {
                      /* Updating failed, or -q triggered.  The STATUS value
                         tells our caller which.  */
                      status = file->update_status;
                      /* If -q just triggered, stop immediately.  It doesn't
                         matter how much more we run, since we already know
                         the answer to return.  */
                      stop = (question_flag && !keep_going_flag
                              && !rebuilding_makefiles);
                    }
                  else
                    {
                      FILE_TIMESTAMP mtime = MTIME (file);
                      check_renamed (file);

                      if (file->updated && g->changed &&
                           mtime != file->mtime_before_update)
                        {
                          /* Updating was done.  If this is a makefile and
                             just_print_flag or question_flag is set (meaning
                             -n or -q was given and this file was specified
                             as a command-line target), don't change STATUS.
                             If STATUS is changed, we will get re-exec'd, and
                             enter an infinite loop.  */
                          if (!rebuilding_makefiles
                              || (!just_print_flag && !question_flag))
                            status = 0;
                          if (rebuilding_makefiles && file->dontcare)
                            /* This is a default makefile; stop remaking.  */
                            stop = 1;
                        }
                    }
                }

	      /* Keep track if any double-colon entry is not finished.
                 When they are all finished, the goal is finished.  */
	      any_not_updated |= !file->updated;

              file->dontcare = 0;

	      if (stop)
		break;
	    }

	  /* Reset FILE since it is null at the end of the loop.  */
	  file = g->file;

	  if (stop || !any_not_updated)
	    {
	      /* If we have found nothing whatever to do for the goal,
		 print a message saying nothing needs doing.  */

	      if (!rebuilding_makefiles
		  /* If the update_status is zero, we updated successfully
		     or not at all.  G->changed will have been set above if
		     any commands were actually started for this goal.  */
		  && file->update_status == 0 && !g->changed
		  /* Never give a message under -s or -q.  */
		  && !silent_flag && !question_flag)
		message (1, ((file->phony || file->cmds == 0)
			     ? _("Nothing to be done for '%s'.")
			     : _("'%s' is up to date.")),
			 file->name);

	      /* This goal is finished.  Remove it from the chain.  */
	      if (lastgoal == 0)
		goals = g->next;
	      else
		lastgoal->next = g->next;

	      /* Free the storage.  */
	      free (g);

	      g = lastgoal == 0 ? goals : lastgoal->next;

	      if (stop)
		break;
	    }
	  else
	    {
	      lastgoal = g;
	      g = g->next;
	    }
	}

      /* If we reached the end of the dependency graph toggle the considered
         flag for the next pass.  */
      if (g == 0)
        considered = !considered;
    }

  if (rebuilding_makefiles)
    {
      touch_flag = t;
      question_flag = q;
      just_print_flag = n;
    }

  return status;
}
Beispiel #19
0
static int delegate_request(struct scgi_server *server, int conn)
{
	fd_set fds;
	int highest_fd, r;
	struct child *child;
	struct timeval timeout;
	char magic;

	timeout.tv_usec = 0;
	timeout.tv_sec = 0;

	while (1) {
		highest_fd = fill_children_fdset(&server->children, &fds);
		r = select(highest_fd + 1, &fds, NULL, NULL, &timeout);
		if (r < 0) {
			if (errno == EINTR) {
				continue;
			} else {
				die("select error");
			}
		} else if (r > 0) {
			/*  One or more children look like they are ready.
			    Do the same walk order so that we keep preferring
			    the same child.
			*/
			child = get_ready_child(&server->children, &fds);
			if (child == NULL) {
				/* should never get here */
				fputs("Ooops\n", stderr);
				continue;
			}

			/*
			  Try to read the single byte written by the child.
			  This can fail if the child died or the pipe really
			  wasn't ready (select returns a hint only).  The fd has
			  been made non-blocking by spawn_child.  If this fails
			  we fall through to the "reap_children" logic and will
			  retry the select call.
			*/

			r = read(child->fd, &magic, 1);
			if (r == -1 && errno != EAGAIN) {
				die("read byte error");
			} else if (r == 1) {
				assert(magic == '1');
				/*
				  The byte was read okay, now we need to pass the fd
				  of the request to the child.  This can also fail
				  if the child died.  Again, if this fails we fall
				  through to the "reap_children" logic and will
				  retry the select call.
				*/
				if (send_fd(child->fd, conn) == -1 && errno != EPIPE) {
					die("sendfd error");
				} else {
					/*
					  fd was apparently passed okay to the child.
					  The child could die before completing the
					  request but that's not our problem anymore.
					*/
					return 0;
				}
			}
		}

		/* didn't find any child, check if any died */
		reap_children(server);

		/* start more children if we haven't met max_children limit */
		if (server->children.size < server->max_children)
			spawn_child(server, conn);

		/* Start blocking inside select.  We might have reached
		   max_children limit and they are all busy.
		*/
		timeout.tv_sec = 2;

	} /* end of while */

	return 0;
}
Beispiel #20
0
RETSIGTYPE
fatal_error_signal (int sig)
{
#ifdef __MSDOS__
    extern int dos_status, dos_command_running;

    if (dos_command_running)
    {
        /* That was the child who got the signal, not us.  */
        dos_status |= (sig << 8);
        return;
    }
    remove_intermediates (1);
    exit (EXIT_FAILURE);
#else /* not __MSDOS__ */
#ifdef _AMIGA
    remove_intermediates (1);
    if (sig == SIGINT)
        fputs (_("*** Break.\n"), stderr);

    exit (10);
#else /* not Amiga */
#ifdef WINDOWS32
    extern HANDLE main_thread;

    /* Windows creates a sperate thread for handling Ctrl+C, so we need
       to suspend the main thread, or else we will have race conditions
       when both threads call reap_children.  */
    if (main_thread)
    {
        DWORD susp_count = SuspendThread (main_thread);

        if (susp_count != 0)
            fprintf (stderr, "SuspendThread: suspend count = %ld\n", susp_count);
        else if (susp_count == (DWORD)-1)
        {
            DWORD ierr = GetLastError ();

            fprintf (stderr, "SuspendThread: error %ld: %s\n",
                     ierr, map_windows32_error_to_string (ierr));
        }
    }
#endif
    handling_fatal_signal = 1;

    /* Set the handling for this signal to the default.
       It is blocked now while we run this handler.  */
    signal (sig, SIG_DFL);

    /* A termination signal won't be sent to the entire
       process group, but it means we want to kill the children.  */

    if (sig == SIGTERM)
    {
        struct child *c;
        for (c = children; c != 0; c = c->next)
            if (!c->remote)
                (void) kill (c->pid, SIGTERM);
    }

    /* If we got a signal that means the user
       wanted to kill make, remove pending targets.  */

    if (sig == SIGTERM || sig == SIGINT
#ifdef SIGHUP
            || sig == SIGHUP
#endif
#ifdef SIGQUIT
            || sig == SIGQUIT
#endif
       )
    {
        struct child *c;

        /* Remote children won't automatically get signals sent
        to the process group, so we must send them.  */
        for (c = children; c != 0; c = c->next)
            if (c->remote)
                (void) remote_kill (c->pid, sig);

        for (c = children; c != 0; c = c->next)
            delete_child_targets (c);

        /* Clean up the children.  We don't just use the call below because
        we don't want to print the "Waiting for children" message.  */
        while (job_slots_used > 0)
            reap_children (1, 0);
    }
    else
        /* Wait for our children to die.  */
        while (job_slots_used > 0)
            reap_children (1, 1);

    /* Delete any non-precious intermediate files that were made.  */

    remove_intermediates (1);

#ifdef SIGQUIT
    if (sig == SIGQUIT)
        /* We don't want to send ourselves SIGQUIT, because it will
           cause a core dump.  Just exit instead.  */
        exit (EXIT_FAILURE);
#endif

#ifdef WINDOWS32
    if (main_thread)
        CloseHandle (main_thread);
    /* Cannot call W32_kill with a pid (it needs a handle).  The exit
       status of 130 emulates what happens in Bash.  */
    exit (130);
#else
    /* Signal the same code; this time it will really be fatal.  The signal
       will be unblocked when we return and arrive then to kill us.  */
    if (kill (getpid (), sig) < 0)
        pfatal_with_name ("kill");
#endif /* not WINDOWS32 */
#endif /* not Amiga */
#endif /* not __MSDOS__  */
}
Beispiel #21
0
// The handler that is invoked when a child process exits:
void handler(int sig) {
	printf("SERVER: Handler invoked.\n");
	reap_children();
}
Beispiel #22
0
/*
 *	Remove a request from the queue.
 */
static int request_dequeue(REQUEST **prequest)
{
	time_t blocked;
	static time_t last_complained = 0;
	RAD_LISTEN_TYPE i, start;
	REQUEST *request;
	reap_children();

	pthread_mutex_lock(&thread_pool.queue_mutex);

#ifdef WITH_STATS
#ifdef WITH_ACCOUNTING
	if (thread_pool.auto_limit_acct) {
		struct timeval now;

		gettimeofday(&now, NULL);
		
		thread_pool.pps_out.pps  = rad_pps(&thread_pool.pps_out.pps_old,
						   &thread_pool.pps_out.pps_now,
						   &thread_pool.pps_out.time_old,
						   &now);
		thread_pool.pps_out.pps_now++;
	}
#endif
#endif

	/*
	 *	Clear old requests from all queues.
	 *
	 *	We only do one pass over the queue, in order to
	 *	amortize the work across the child threads.  Since we
	 *	do N checks for one request de-queued, the old
	 *	requests will be quickly cleared.
	 */
	for (i = 0; i < RAD_LISTEN_MAX; i++) {
		request = fr_fifo_peek(thread_pool.fifo[i]);
		if (!request) continue;

		rad_assert(request->magic == REQUEST_MAGIC);

		if (request->master_state != REQUEST_STOP_PROCESSING) {
			continue;
		}

		/*
		 *	This entry was marked to be stopped.  Acknowledge it.
		 */
		request = fr_fifo_pop(thread_pool.fifo[i]);
		rad_assert(request != NULL);
		request->child_state = REQUEST_DONE;
		thread_pool.num_queued--;
	}

	start = 0;
 retry:
	/*
	 *	Pop results from the top of the queue
	 */
	for (i = start; i < RAD_LISTEN_MAX; i++) {
		request = fr_fifo_pop(thread_pool.fifo[i]);
		if (request) {
			start = i;
			break;
		}
	}

	if (!request) {
		pthread_mutex_unlock(&thread_pool.queue_mutex);
		*prequest = NULL;
		return 0;
	}

	rad_assert(thread_pool.num_queued > 0);
	thread_pool.num_queued--;
	*prequest = request;

	rad_assert(*prequest != NULL);
	rad_assert(request->magic == REQUEST_MAGIC);

	request->component = "<core>";
	request->module = "<thread>";

	/*
	 *	If the request has sat in the queue for too long,
	 *	kill it.
	 *
	 *	The main clean-up code can't delete the request from
	 *	the queue, and therefore won't clean it up until we
	 *	have acknowledged it as "done".
	 */
	if (request->master_state == REQUEST_STOP_PROCESSING) {
		request->module = "<done>";
		request->child_state = REQUEST_DONE;
		goto retry;
	}

	/*
	 *	The thread is currently processing a request.
	 */
	thread_pool.active_threads++;

	blocked = time(NULL);
	if ((blocked - request->timestamp) > 5) {
		if (last_complained < blocked) {
			last_complained = blocked;
			blocked -= request->timestamp;
		} else {
			blocked = 0;
		}
	} else {
		blocked = 0;
	}

	pthread_mutex_unlock(&thread_pool.queue_mutex);

	if (blocked) {
		radlog(L_ERR, "(%u) %s has been waiting in the processing queue for %d seconds.  Check that all databases are running properly!",
		       request->number, fr_packet_codes[request->packet->code], (int) blocked);
	}

	return 1;
}
Beispiel #23
0
/*
 *	Remove a request from the queue.
 */
static int request_dequeue(REQUEST **prequest, RAD_REQUEST_FUNP *fun)
{
	RAD_LISTEN_TYPE i, start;
	REQUEST *request = NULL;

	reap_children();

	pthread_mutex_lock(&thread_pool.queue_mutex);

	/*
	 *	Clear old requests from all queues.
	 *
	 *	We only do one pass over the queue, in order to
	 *	amortize the work across the child threads.  Since we
	 *	do N checks for one request de-queued, the old
	 *	requests will be quickly cleared.
	 */
	for (i = 0; i < RAD_LISTEN_MAX; i++) {
		request = fr_fifo_peek(thread_pool.fifo[i]);
		if (!request ||
		    (request->master_state != REQUEST_STOP_PROCESSING)) {
			continue;
}
		/*
		 *	This entry was marked to be stopped.  Acknowledge it.
		 */
		request = fr_fifo_pop(thread_pool.fifo[i]);
		rad_assert(request != NULL);
		request->child_state = REQUEST_DONE;
		thread_pool.num_queued--;
	}

	start = 0;
 retry:
	/*
	 *	Pop results from the top of the queue
	 */
	for (i = start; i < RAD_LISTEN_MAX; i++) {
		request = fr_fifo_pop(thread_pool.fifo[i]);
		if (request) {
			start = i;
			break;
		}
	}

	if (!request) {
		pthread_mutex_unlock(&thread_pool.queue_mutex);
		*prequest = NULL;
		*fun = NULL;
		return 0;
	}

	rad_assert(thread_pool.num_queued > 0);
	thread_pool.num_queued--;
	*prequest = request;
	*fun = request->process;

	rad_assert(request->magic == REQUEST_MAGIC);
	rad_assert(*fun != NULL);

	/*
	 *	If the request has sat in the queue for too long,
	 *	kill it.
	 *
	 *	The main clean-up code can't delete the request from
	 *	the queue, and therefore won't clean it up until we
	 *	have acknowledged it as "done".
	 */
	if (request->master_state == REQUEST_STOP_PROCESSING) {
		request->child_state = REQUEST_DONE;
		goto retry;
	}

	/*
	 *	The thread is currently processing a request.
	 */
	thread_pool.active_threads++;

	pthread_mutex_unlock(&thread_pool.queue_mutex);

	return 1;
}