Example #1
0
static void spawn_haproxy(char **pid_strv, int nb_pid)
{
	char haproxy_bin[512];
	pid_t pid;
	int main_argc;
	char **main_argv;

	main_argc = wrapper_argc - 1;
	main_argv = wrapper_argv + 1;

	//pid = fork();
	pid=0;
	if (!pid) {
		/* 3 for "haproxy -Ds -sf" */
		char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *));
		int i;
		int argno = 0;
		locate_haproxy(haproxy_bin, 512);
		argv[argno++] = haproxy_bin;
		for (i = 0; i < main_argc; ++i)
			argv[argno++] = main_argv[i];
		argv[argno++] = "-Ds";
		if (nb_pid > 0) {
			argv[argno++] = "-sf";
			for (i = 0; i < nb_pid; ++i)
				argv[argno++] = pid_strv[i];
		}
		argv[argno] = NULL;

		fprintf(stderr, SD_DEBUG "haproxy-systemd-wrapper: executing ");
		for (i = 0; argv[i]; ++i)
			fprintf(stderr, "%s ", argv[i]);
		fprintf(stderr, "\n");

		execv(argv[0], argv);
		exit(0);
	}
}
/* Note: this function must not exit in case of error (except in the child), as
 * it is only dedicated the starting a new haproxy process. By keeping the
 * process alive it will ensure that future signal delivery may get rid of
 * the issue. If the first startup fails, the wrapper will notice it and
 * return an error thanks to wait() returning ECHILD.
 */
static void spawn_haproxy(char **pid_strv, int nb_pid)
{
	char haproxy_bin[512];
	pid_t pid;
	int main_argc;
	char **main_argv;
	int pipefd[2];
	char fdstr[20];
	int ret;

	main_argc = wrapper_argc - 1;
	main_argv = wrapper_argv + 1;

	if (pipe(pipefd) != 0) {
		fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to create a pipe, please try again later.\n");
		return;
	}

	pid = fork();
	if (!pid) {
		char **argv;
		int i;
		int argno = 0;

		/* 3 for "haproxy -Ds -sf" */
		argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *));
		if (!argv) {
			fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to calloc(), please try again later.\n");
			exit(1);
		}

		reset_signal_handler();

		close(pipefd[0]); /* close the read side */

		snprintf(fdstr, sizeof(fdstr), "%d", pipefd[1]);
		if (setenv("HAPROXY_WRAPPER_FD", fdstr, 1) != 0) {
			fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to setenv(), please try again later.\n");
			exit(1);
		}

		locate_haproxy(haproxy_bin, 512);
		argv[argno++] = haproxy_bin;
		for (i = 0; i < main_argc; ++i)
			argv[argno++] = main_argv[i];
		argv[argno++] = "-Ds";
		if (nb_pid > 0) {
			argv[argno++] = "-sf";
			for (i = 0; i < nb_pid; ++i)
				argv[argno++] = pid_strv[i];
		}
		argv[argno] = NULL;

		fprintf(stderr, SD_DEBUG "haproxy-systemd-wrapper: executing ");
		for (i = 0; argv[i]; ++i)
			fprintf(stderr, "%s ", argv[i]);
		fprintf(stderr, "\n");

		execv(argv[0], argv);
		fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: execv(%s) failed, please try again later.\n", argv[0]);
		exit(1);
	}
	else if (pid == -1) {
		fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: failed to fork(), please try again later.\n");
	}

	/* The parent closes the write side and waits for the child to close it
	 * as well. Also deal the case where the fd would unexpectedly be 1 or 2
	 * by silently draining all data.
	 */
	close(pipefd[1]);

	do {
		char c;
		ret = read(pipefd[0], &c, sizeof(c));
	} while ((ret > 0) || (ret == -1 && errno == EINTR));
	/* the child has finished starting up */
	close(pipefd[0]);
}