예제 #1
0
파일: multi_server.c 프로젝트: LMDB/postfix
int     multi_server_drain(void)
{
    const char *myname = "multi_server_drain";
    int     fd;

    switch (fork()) {
	/* Try again later. */
    case -1:
	return (-1);
	/* Finish existing clients in the background, then terminate. */
    case 0:
	(void) msg_cleanup((MSG_CLEANUP_FN) 0);
	event_fork();
	for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) {
	    event_disable_readwrite(fd);
	    (void) close(fd);
	    /* Play safe - don't reuse this file number. */
	    if (DUP2(STDIN_FILENO, fd) < 0)
		msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
	}
	var_use_limit = 1;
	return (0);
	/* Let the master start a new process. */
    default:
	exit(0);
    }
}
예제 #2
0
void HELPER(gvec_ors)(void *d, void *a, uint64_t b, uint32_t desc)
{
    intptr_t oprsz = simd_oprsz(desc);
    vec64 vecb = (vec64)DUP2(b);
    intptr_t i;

    for (i = 0; i < oprsz; i += sizeof(vec64)) {
        *(vec64 *)(d + i) = *(vec64 *)(a + i) | vecb;
    }
    clear_high(d, oprsz, desc);
}
예제 #3
0
파일: scache.c 프로젝트: DabeDotCom/postfix
static void save_endp(ARGV *argv)
{
    int     ttl;
    int     fd;

    if (argv->argc != 5
	|| (ttl = atoi(argv->argv[1])) <= 0
	|| (fd = atoi(argv->argv[4])) <= 0) {
	msg_error("usage: save_endp ttl endpoint endp_props fd");
	return;
    }
    if (DUP2(0, fd) < 0)
	msg_fatal("dup2(0, %d): %m", fd);
    scache_save_endp(scache, ttl, argv->argv[2], argv->argv[3], fd);
}
예제 #4
0
파일: gtm_pipe.c 프로젝트: 5HT/mumps
int gtm_pipe(char *command, pipe_type pt)
{
	int 	pfd[2], child, parent;
	int	dup2_res;
	pid_t	child_pid;

	parent = (int)pt;
	child  = 1 - parent;

	if (0 > pipe(pfd))
	{
		PERROR("pipe : ");
		return -2;
	}

	if(-1 == (child_pid = fork()))
	{
		PERROR("fork : ");
		return -1;
	}
	else if (0 == child_pid)
	{
		/* child process */
		close(pfd[parent]);
		DUP2(pfd[child], child, dup2_res);
		close(pfd[child]);
		/*
		 * we should have used exec instead of SYSTEM.
		 * Earlier it was followed by exit(0), which calls exit_handler.
		 * So both child and parent will do exit handling. This can make ref_cnt < 0, or,
		 * it can release semaphores, which we should not rlease until parent exists.
		 * So we just call _exit(0)
		 */
		SYSTEM(command);
		_exit(0); /* just exit from here */
	}
	else
	{
		/* parent process */
		pipe_child = child_pid;
		close(pfd[child]);
   		return pfd[parent];
	}

	assert(FALSE);
	/* It should never get here, just to keep compiler happy. */
	return -3;
}
예제 #5
0
파일: gtm_pipe.c 프로젝트: indera/fis-gtm
int gtm_pipe(char *command, pipe_type pt)
{
    int 	pfd[2], child, parent;
    int	dup2_res, rc;
    pid_t	child_pid;

    parent = (int)pt;
    child  = 1 - parent;

    if (0 > pipe(pfd))
    {
        PERROR("pipe : ");
        return -2;
    }
    if (-1 == (child_pid = fork()))	/* BYPASSOK: we exit immediately, no FORK_CLEAN needed */
    {
        PERROR("fork : ");
        return -1;
    } else if (0 == child_pid)
    {   /* child process */
        CLOSEFILE_RESET(pfd[parent], rc);	/* resets "pfd[parent]" to FD_INVALID */
        DUP2(pfd[child], child, dup2_res);
        CLOSEFILE_RESET(pfd[child], rc);	/* resets "pfd[child]" to FD_INVALID */
        /* We should have used exec instead of SYSTEM. Earlier it was followed by exit(0), which calls exit_handler.
         * So both child and parent will do exit handling. This can make ref_cnt < 0, or, it can release semaphores,
         * which we should not release until parent exists. So we just call _exit(0).  Add the do nothing if to
         * keep compiler happy since exiting anyway.
         */
        if (-1 == SYSTEM(command));
        _exit(0); /* just exit from here */
    } else
    {   /* parent process */
        pipe_child = child_pid;
        CLOSEFILE_RESET(pfd[child], rc);	/* resets "pfd[child]" to FD_INVALID */
        return pfd[parent];
    }

    assert(FALSE);
    /* It should never get here, just to keep compiler happy. */
    return -3;
}
예제 #6
0
int gtm_pipe(char *command, pipe_type pt)
{
	int 	pfd[2], child, parent;
	int	dup2_res, rc;
	pid_t	child_pid;

	parent = (int)pt;
	child  = 1 - parent;
	if (0 > pipe(pfd))
	{
		PERROR("pipe : ");
		return -2;
	}
	FORK(child_pid);
	if (-1 == child_pid)
	{
		PERROR("fork : ");
		return -1;
	} else if (0 == child_pid)
	{	/* child process */
		CLOSEFILE_RESET(pfd[parent], rc);	/* resets "pfd[parent]" to FD_INVALID */
		DUP2(pfd[child], child, dup2_res);
		CLOSEFILE_RESET(pfd[child], rc);	/* resets "pfd[child]" to FD_INVALID */
		/* We should have used exec instead of SYSTEM. Earlier it was followed by exit(EXIT_SUCCESS), which calls
		 * exit_handler.  So both child and parent will do exit handling. This can make ref_cnt < 0, or, it can release
		 * semaphores, which we should not release until parent exists. So we just call _exit(EXIT_SUCCESS).  Add the do
		 * nothing if to keep compiler happy since exiting anyway.
		 */
		rc = SYSTEM(command);
		_exit(EXIT_SUCCESS); /* just exit from here */
	} else
	{	/* parent process */
		pipe_child = child_pid;
		CLOSEFILE_RESET(pfd[child], rc);	/* resets "pfd[child]" to FD_INVALID */
   		return pfd[parent];
	}
}
예제 #7
0
void    master_spawn(MASTER_SERV *serv)
{
    const char *myname = "master_spawn";
    MASTER_PROC *proc;
    MASTER_PID pid;
    int     n;
    static unsigned master_generation = 0;
    static VSTRING *env_gen = 0;

    if (master_child_table == 0)
	master_child_table = binhash_create(0);
    if (env_gen == 0)
	env_gen = vstring_alloc(100);

    /*
     * Sanity checks. The master_avail module is supposed to know what it is
     * doing.
     */
    if (!MASTER_LIMIT_OK(serv->max_proc, serv->total_proc))
	msg_panic("%s: at process limit %d", myname, serv->total_proc);
    if (serv->avail_proc > 0)
	msg_panic("%s: processes available: %d", myname, serv->avail_proc);
    if (serv->flags & MASTER_FLAG_THROTTLE)
	msg_panic("%s: throttled service: %s", myname, serv->path);

    /*
     * Create a child process and connect parent and child via the status
     * pipe.
     */
    master_generation += 1;
    switch (pid = fork()) {

	/*
	 * Error. We're out of some essential resource. Best recourse is to
	 * try again later.
	 */
    case -1:
	msg_warn("%s: fork: %m -- throttling", myname);
	master_throttle(serv);
	return;

	/*
	 * Child process. Redirect child stdin/stdout to the parent-child
	 * connection and run the requested command. Leave child stderr
	 * alone. Disable exit handlers: they should be executed by the
	 * parent only.
	 * 
	 * When we reach the process limit on a public internet service, we
	 * create stress-mode processes until the process count stays below
	 * the limit for some amount of time. See master_avail_listen().
	 */
    case 0:
	msg_cleanup((void (*) (void)) 0);	/* disable exit handler */
	closelog();				/* avoid filedes leak */

	if (master_flow_pipe[0] <= MASTER_FLOW_READ)
	    msg_fatal("%s: flow pipe read descriptor <= %d",
		      myname, MASTER_FLOW_READ);
	if (DUP2(master_flow_pipe[0], MASTER_FLOW_READ) < 0)
	    msg_fatal("%s: dup2: %m", myname);
	if (close(master_flow_pipe[0]) < 0)
	    msg_fatal("close %d: %m", master_flow_pipe[0]);

	if (master_flow_pipe[1] <= MASTER_FLOW_WRITE)
	    msg_fatal("%s: flow pipe read descriptor <= %d",
		      myname, MASTER_FLOW_WRITE);
	if (DUP2(master_flow_pipe[1], MASTER_FLOW_WRITE) < 0)
	    msg_fatal("%s: dup2: %m", myname);
	if (close(master_flow_pipe[1]) < 0)
	    msg_fatal("close %d: %m", master_flow_pipe[1]);

	close(serv->status_fd[0]);		/* status channel */
	if (serv->status_fd[1] <= MASTER_STATUS_FD)
	    msg_fatal("%s: status file descriptor collision", myname);
	if (DUP2(serv->status_fd[1], MASTER_STATUS_FD) < 0)
	    msg_fatal("%s: dup2 status_fd: %m", myname);
	(void) close(serv->status_fd[1]);

	for (n = 0; n < serv->listen_fd_count; n++) {
	    if (serv->listen_fd[n] <= MASTER_LISTEN_FD + n)
		msg_fatal("%s: listen file descriptor collision", myname);
	    if (DUP2(serv->listen_fd[n], MASTER_LISTEN_FD + n) < 0)
		msg_fatal("%s: dup2 listen_fd %d: %m",
			  myname, serv->listen_fd[n]);
	    (void) close(serv->listen_fd[n]);
	}
	vstring_sprintf(env_gen, "%s=%o", MASTER_GEN_NAME, master_generation);
	if (putenv(vstring_str(env_gen)) < 0)
	    msg_fatal("%s: putenv: %m", myname);
	if (serv->stress_param_val && serv->stress_expire_time > event_time())
	    serv->stress_param_val[0] = CONFIG_BOOL_YES[0];

	execvp(serv->path, serv->args->argv);
	msg_fatal("%s: exec %s: %m", myname, serv->path);
	/* NOTREACHED */

	/*
	 * Parent. Fill in a process member data structure and set up links
	 * between child and process. Say this process has become available.
	 * If this service has a wakeup timer that is turned on only when the
	 * service is actually used, turn on the wakeup timer.
	 */
    default:
	if (msg_verbose)
	    msg_info("spawn command %s; pid %d", serv->path, pid);
	proc = (MASTER_PROC *) mymalloc(sizeof(MASTER_PROC));
	proc->serv = serv;
	proc->pid = pid;
	proc->gen = master_generation;
	proc->use_count = 0;
	proc->avail = 0;
	binhash_enter(master_child_table, (void *) &pid,
		      sizeof(pid), (void *) proc);
	serv->total_proc++;
	master_avail_more(serv, proc);
	if (serv->flags & MASTER_FLAG_CONDWAKE) {
	    serv->flags &= ~MASTER_FLAG_CONDWAKE;
	    master_wakeup_init(serv);
	    if (msg_verbose)
		msg_info("start conditional timer for %s", serv->name);
	}
	return;
    }
}
예제 #8
0
int repl_log_init(repl_log_file_t log_type,
		  int *log_fd,
		  int *stats_fd,
		  char *log,
		  char *stats_log)
{
	/* Open the log file */

	char	log_file_name[MAX_FN_LEN + 1], *err_code;
	int	tmp_fd;
	int	save_errno;
	int	stdout_status, stderr_status;

	error_def(ERR_REPLLOGOPN);
	error_def(ERR_TEXT);

	if (*log == '\0')
		return(EREPL_LOGFILEOPEN);

	strcpy(log_file_name, log);
	if (log_type == REPL_STATISTICS_LOG)
	{
		if (strcmp(log_file_name, stats_log) != 0)
			strcpy(log_file_name, stats_log);
		else
		{
			*stats_fd = *log_fd;
			return(SS_NORMAL);
		}
	}

	OPENFILE3(log_file_name, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, tmp_fd);
	if (tmp_fd < 0)
	{
		if (log_type == REPL_GENERAL_LOG && *log_fd == -1 || *stats_fd == -1)
		{
			save_errno = ERRNO;
			err_code = STRERROR(save_errno);
			send_msg(VARLSTCNT(8) ERR_REPLLOGOPN, 6,
			 	 LEN_AND_STR(log_file_name),
				 LEN_AND_STR(err_code),
				 LEN_AND_STR(NULL_DEVICE));
			strcpy(log_file_name, NULL_DEVICE);
			if (log_type == REPL_GENERAL_LOG)
				strcpy(log, log_file_name);
			else
				strcpy(stats_log, log_file_name);
			OPENFILE(log_file_name, O_RDWR, tmp_fd); /* Should not fail */
		} else
		{
			save_errno = ERRNO;
			err_code = STRERROR(save_errno);
			gtm_putmsg(VARLSTCNT(8) ERR_REPLLOGOPN, 6,
			 	   LEN_AND_STR(log_file_name),
				   LEN_AND_STR(err_code),
				   (log_type == REPL_GENERAL_LOG) ?
				   strlen(log) : strlen(stats_log),
				   (log_type == REPL_GENERAL_LOG) ?
				   log : stats_log);

			return(EREPL_LOGFILEOPEN);
		}
	}

	if (log_type == REPL_GENERAL_LOG)
	{
		int dup2_res;
		/* Duplicate stdout and stderr onto log file */
		DUP2(tmp_fd, 1, stdout_status);
		if (stdout_status >= 0)
		{
			DUP2(tmp_fd, 2, stderr_status);
			if (stderr_status < 0)
			{
				save_errno = ERRNO;
				if (*log_fd != -1)
				{
					DUP2(*log_fd, 1, dup2_res); /* Restore old log file */
					DUP2(*log_fd, 2, dup2_res);
				}
			}
		} else
		{
			save_errno = ERRNO;
			if (*log_fd != -1)
				DUP2(*log_fd, 1, dup2_res); /* Restore old log file */
		}

		if (stdout_status >= 0 && stderr_status >= 0)
		{
			if (*log_fd != -1)
				close(*log_fd);
			*log_fd = tmp_fd;
		} else
		{
			err_code = STRERROR(save_errno);
			gtm_putmsg(VARLSTCNT(10) ERR_REPLLOGOPN, 6,
			 	   LEN_AND_STR(log_file_name),
				   LEN_AND_STR(err_code),
				   (log_type == REPL_GENERAL_LOG) ?
				   strlen(log) : strlen(stats_log),
				   (log_type == REPL_GENERAL_LOG) ?
				   log : stats_log,
				   ERR_TEXT, 2, RTS_ERROR_LITERAL("Error in dup2"));
		}
	} else
	{
		if (*stats_fd != -1)
			close(*stats_fd);
		*stats_fd = tmp_fd;
	}

	return(SS_NORMAL);
}