Пример #1
0
Файл: emperor.c Проект: ahua/c
void uwsgi_emperor_start() {

	if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
		if (uwsgi.emperor_procname) {
			uwsgi_set_processname(uwsgi.emperor_procname);
		}
		uwsgi_notify_ready();
		emperor_loop();
		// never here
		exit(1);
	}

	if (uwsgi.emperor_procname) {
		uwsgi.emperor_pid = uwsgi_fork(uwsgi.emperor_procname);
	}
	else {
		uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
	}

	if (uwsgi.emperor_pid < 0) {
		uwsgi_error("pid()");
		exit(1);
	}
	else if (uwsgi.emperor_pid == 0) {
#ifdef __linux__
		if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
			uwsgi_error("prctl()");
		}
#endif
		emperor_loop();
		// never here
		exit(1);
	}

}
Пример #2
0
void uwsgi_mule(int id) {

	int i;

	pid_t pid = uwsgi_fork(uwsgi.mules[id - 1].name);
	if (pid == 0) {
#ifdef __linux__
		if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
			uwsgi_error("prctl()");
		}
#endif
		uwsgi.muleid = id;
		// avoid race conditions
		uwsgi.mules[id - 1].id = id;
		uwsgi.mules[id - 1].pid = getpid();

		uwsgi_fixup_fds(0, id, NULL);

		uwsgi.my_signal_socket = uwsgi.mules[id - 1].signal_pipe[1];
		uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];

		uwsgi_close_all_sockets();

		for (i = 0; i < 256; i++) {
			if (uwsgi.p[i]->master_fixup) {
				uwsgi.p[i]->master_fixup(1);
			}
		}

		for (i = 0; i < 256; i++) {
			if (uwsgi.p[i]->post_fork) {
				uwsgi.p[i]->post_fork();
			}
		}


		if (uwsgi.mules[id - 1].patch) {
			for (i = 0; i < 256; i++) {
				if (uwsgi.p[i]->mule) {
					if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
						// never here
						break;
					}
				}
			}
		}

		uwsgi_mule_handler();
	}
	else if (pid > 0) {
		uwsgi.mules[id - 1].id = id;
		uwsgi.mules[id - 1].pid = pid;
		uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
	}
}
Пример #3
0
void gateway_respawn(int id) {

	pid_t gw_pid;
	struct uwsgi_gateway *ug = &ushared->gateways[id];

	if (uwsgi.master_process)
		uwsgi.shared->gateways_harakiri[id] = 0;

	gw_pid = uwsgi_fork(ug->fullname);
	if (gw_pid < 0) {
		uwsgi_error("fork()");
		return;
	}

	if (gw_pid == 0) {
		uwsgi_fixup_fds(0, 0, ug);
		if (uwsgi.master_as_root)
			uwsgi_as_root();
#ifdef __linux__
		if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
			uwsgi_error("prctl()");
		}
#endif
		uwsgi.mypid = getpid();
		atexit(gateway_brutal_end);
		signal(SIGALRM, SIG_IGN);
		signal(SIGHUP, SIG_IGN);
		signal(SIGINT, end_me);
		signal(SIGTERM, end_me);
		signal(SIGUSR1, SIG_IGN);
		signal(SIGUSR2, SIG_IGN);
		signal(SIGPIPE, SIG_IGN);
		signal(SIGSTOP, SIG_IGN);
		signal(SIGTSTP, SIG_IGN);

		ug->loop(id, ug->data);
		// never here !!! (i hope)
		exit(1);
	}

	ug->pid = gw_pid;
	ug->respawns++;
	if (ug->respawns == 1) {
		uwsgi_log("spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
	}
	else {
		uwsgi_log("respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
	}

}
Пример #4
0
void uwsgi_mule(int id) {

	int i;

	pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
	if (pid == 0) {
		uwsgi.muleid = id;
		// avoid race conditions
		uwsgi.mules[id-1].id = id;
		uwsgi.mules[id-1].pid = getpid();

		uwsgi_fixup_fds(0, id);

		uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
		uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];

		uwsgi_close_all_sockets();

		for (i = 0; i < 0xFF; i++) {
                	if (uwsgi.p[i]->master_fixup) {
                		uwsgi.p[i]->master_fixup(1);
                	}
                }

		for (i = 0; i < 0xFF; i++) {
                        if (uwsgi.p[i]->post_fork) {
                                uwsgi.p[i]->post_fork();
                        }
                }


		if (uwsgi.mules[id-1].patch) {
			for (i = 0; i < 0xFF; i++) {
                        	if (uwsgi.p[i]->mule) {
                                	if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
						// never here
						break;
					}
				}
                        }
		}

		uwsgi_mule_handler();
	}
	else if (pid > 0) {
		uwsgi.mules[id-1].id = id;
		uwsgi.mules[id-1].pid = pid;
		uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
	}
}
Пример #5
0
pid_t spooler_start(struct uwsgi_spooler *uspool) {

    int i;

    pid_t pid = uwsgi_fork("uWSGI spooler");
    if (pid < 0) {
        uwsgi_error("fork()");
        exit(1);
    }
    else if (pid == 0) {
        // USR1 will be used to wake up the spooler
        uwsgi_unix_signal(SIGUSR1, spooler_wakeup);
        uwsgi.mywid = -1;
        uwsgi.mypid = getpid();
        uspool->pid = uwsgi.mypid;
        // avoid race conditions !!!
        uwsgi.i_am_a_spooler = uspool;

        uwsgi_fixup_fds(0, 0, NULL);
        uwsgi_close_all_sockets();

        for (i = 0; i < 256; i++) {
            if (uwsgi.p[i]->post_fork) {
                uwsgi.p[i]->post_fork();
            }
        }

        uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];

        for (i = 0; i < 256; i++) {
            if (uwsgi.p[i]->spooler_init) {
                uwsgi.p[i]->spooler_init();
            }
        }

        for (i = 0; i < uwsgi.gp_cnt; i++) {
            if (uwsgi.gp[i]->spooler_init) {
                uwsgi.gp[i]->spooler_init();
            }
        }

        spooler(uspool);
    }
    else if (pid > 0) {
        uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
    }

    return pid;
}
Пример #6
0
pid_t spooler_start(struct uwsgi_spooler * uspool) {

	int i;

	pid_t pid = uwsgi_fork("uWSGI spooler");
	if (pid < 0) {
		uwsgi_error("fork()");
		exit(1);
	}
	else if (pid == 0) {

		signal(SIGALRM, SIG_IGN);
                signal(SIGHUP, SIG_IGN);
                signal(SIGINT, end_me);
                signal(SIGTERM, end_me);
		// USR1 will be used to wake up the spooler
		uwsgi_unix_signal(SIGUSR1, spooler_wakeup);
                signal(SIGUSR2, SIG_IGN);
                signal(SIGPIPE, SIG_IGN);
                signal(SIGSTOP, SIG_IGN);
                signal(SIGTSTP, SIG_IGN);

		uwsgi.mypid = getpid();
		uspool->pid = uwsgi.mypid;
		// avoid race conditions !!!
		uwsgi.i_am_a_spooler = uspool;

		uwsgi_fixup_fds(0, 0, NULL);
		uwsgi_close_all_sockets();

		for (i = 0; i < 256; i++) {
			if (uwsgi.p[i]->post_fork) {
				uwsgi.p[i]->post_fork();
			}
		}

		uwsgi_spooler_run();
	}
	else if (pid > 0) {
		uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
	}

	return pid;
}
Пример #7
0
int uwsgi_respawn_worker(int wid) {

	int respawns = uwsgi.workers[wid].respawn_count;
	int i;

	if (uwsgi.threaded_logger) {
		pthread_mutex_lock(&uwsgi.threaded_logger_lock);
	}

	pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);

	if (pid == 0) {
		signal(SIGWINCH, worker_wakeup);
		signal(SIGTSTP, worker_wakeup);
		uwsgi.mywid = wid;
		uwsgi.mypid = getpid();
		uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
		uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
		uwsgi.workers[uwsgi.mywid].harakiri = 0;

		uwsgi.workers[uwsgi.mywid].rss_size = 0;
		uwsgi.workers[uwsgi.mywid].vsz_size = 0;
		// do not reset worker counters on reload !!!
		//uwsgi.workers[uwsgi.mywid].requests = 0;
		// ...but maintain a delta counter (yes this is racy in multithread)
		uwsgi.workers[uwsgi.mywid].delta_requests = 0;
		//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
		uwsgi.workers[uwsgi.mywid].respawn_count++;
		uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
		uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
		uwsgi.workers[uwsgi.mywid].cheaped = 0;
		uwsgi.workers[uwsgi.mywid].busy = 0;
		uwsgi.workers[uwsgi.mywid].suspended = 0;
		uwsgi.workers[uwsgi.mywid].sig = 0;

		// reset the apps count with a copy from the master 
		uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;

		uwsgi_fixup_fds(wid, 0, NULL);

		uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];

		if (uwsgi.master_process) {
			if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
				for (i = 0; i < 256; i++) {
					if (uwsgi.p[i]->master_fixup) {
						uwsgi.p[i]->master_fixup(1);
					}
				}
			}
		}

		return 1;
	}
	else if (pid < 1) {
		uwsgi_error("fork()");
	}
	else {
		if (respawns > 0) {
			uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
		}
		else {
			uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
		}
	}

	if (uwsgi.threaded_logger) {
		pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
	}


	return 0;
}
Пример #8
0
int uwsgi_respawn_worker(int wid) {

	int respawns = uwsgi.workers[wid].respawn_count;
	// we count the respawns before errors...
	uwsgi.workers[wid].respawn_count++;
	// ... same for update time
	uwsgi.workers[wid].last_spawn = uwsgi.current_time;
	// ... and memory/harakiri
	uwsgi.workers[wid].harakiri = 0;
	uwsgi.workers[wid].user_harakiri = 0;
	uwsgi.workers[wid].pending_harakiri = 0;
	uwsgi.workers[wid].rss_size = 0;
	uwsgi.workers[wid].vsz_size = 0;
	// ... reset stopped_at
	uwsgi.workers[wid].cursed_at = 0;
	uwsgi.workers[wid].no_mercy_at = 0;

	// internal statuses should be reset too

	uwsgi.workers[wid].cheaped = 0;
	// SUSPENSION is managed by the user, not the master...
	//uwsgi.workers[wid].suspended = 0;
	uwsgi.workers[wid].sig = 0;

	// this is required for various checks
	uwsgi.workers[wid].delta_requests = 0;

	int i;

	if (uwsgi.threaded_logger) {
		pthread_mutex_lock(&uwsgi.threaded_logger_lock);
	}

	pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);

	if (pid == 0) {
		signal(SIGWINCH, worker_wakeup);
		signal(SIGTSTP, worker_wakeup);
		uwsgi.mywid = wid;
		uwsgi.mypid = getpid();
		// pid is updated by the master
		//uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
		// OVERENGINEERING (just to be safe)
		uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
		/*
		   uwsgi.workers[uwsgi.mywid].harakiri = 0;
		   uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
		   uwsgi.workers[uwsgi.mywid].rss_size = 0;
		   uwsgi.workers[uwsgi.mywid].vsz_size = 0;
		 */
		// do not reset worker counters on reload !!!
		//uwsgi.workers[uwsgi.mywid].requests = 0;
		// ...but maintain a delta counter (yes this is racy in multithread)
		//uwsgi.workers[uwsgi.mywid].delta_requests = 0;
		//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
		//uwsgi.workers[uwsgi.mywid].respawn_count++;
		//uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
		uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
		/*
		   uwsgi.workers[uwsgi.mywid].cheaped = 0;
		   uwsgi.workers[uwsgi.mywid].suspended = 0;
		   uwsgi.workers[uwsgi.mywid].sig = 0;
		 */

		// reset the apps count with a copy from the master 
		uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;

		// reset wsgi_request structures
		for(i=0;i<uwsgi.cores;i++) {
			uwsgi.workers[uwsgi.mywid].cores[i].in_request = 0;
			memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
		}

		uwsgi_fixup_fds(wid, 0, NULL);

		uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];

		if (uwsgi.master_process) {
			if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.status.is_cheap)) {
				for (i = 0; i < 256; i++) {
					if (uwsgi.p[i]->master_fixup) {
						uwsgi.p[i]->master_fixup(1);
					}
				}
			}
		}

		return 1;
	}
	else if (pid < 1) {
		uwsgi_error("fork()");
	}
	else {
		// the pid is set only in the master, as the worker should never use it
		uwsgi.workers[wid].pid = pid;

		if (respawns > 0) {
			uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
		}
		else {
			uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
		}
	}

	if (uwsgi.threaded_logger) {
		pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
	}


	return 0;
}
Пример #9
0
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {

	int devnull = -1;
	int throttle = 0;

	if (uwsgi.current_time - ud->last_spawn <= 3) {
		throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
	}

	pid_t pid = uwsgi_fork("uWSGI external daemon");
	if (pid < 0) {
		uwsgi_error("fork()");
		return;
	}

	if (pid > 0) {
		ud->pid = pid;
		ud->status = 1;
		ud->pidfile_checks = 0;
		if (ud->respawns == 0) {
			ud->born = uwsgi_now();
		}

		ud->respawns++;
		ud->last_spawn = uwsgi_now();

	}
	else {
		// close uwsgi sockets
		uwsgi_close_all_sockets();

		if (ud->daemonize) {
			/* refork... */
			pid = fork();
			if (pid < 0) {
				uwsgi_error("fork()");
				exit(1);
			}
			if (pid != 0) {
				_exit(0);
			}
			uwsgi_write_pidfile(ud->pidfile);
		}

		// /dev/null will became stdin
		devnull = open("/dev/null", O_RDONLY);
		if (devnull < 0) {
			uwsgi_error("/dev/null open()");
			exit(1);
		}
		if (devnull != 0) {
			if (dup2(devnull, 0)) {
				uwsgi_error("dup2()");
				exit(1);
			}
			close(devnull);
		}

		if (setsid() < 0) {
			uwsgi_error("setsid()");
			exit(1);
		}

		if (!ud->pidfile) {
#ifdef __linux__
			if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
				uwsgi_error("prctl()");
			}
#endif
		}


		if (throttle) {
			uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
			sleep(throttle);
		}

		uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
		uwsgi_exec_command_with_args(ud->command);
		uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);

		// never here;
		exit(1);
	}

	return;
}
Пример #10
0
void uwsgi_detach_daemons() {
	struct uwsgi_daemon *ud = uwsgi.daemons;
	while (ud) {
#ifdef UWSGI_SSL
		// stop any legion daemon, doesn't matter if dumb or smart
		if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
#else
		// stop only dumb daemons
		if (ud->pid > 0 && !ud->pidfile) {
#endif
			uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
			// try to stop daemon gracefully, kill it if it won't die
			// if mercy is not set then wait up to 3 seconds
			time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
			int waitpid_status;
			while (!kill(ud->pid, 0)) {
				kill(-ud->pid, ud->stop_signal);
				sleep(1);
				waitpid(-ud->pid, &waitpid_status, WNOHANG);
				if (uwsgi_now() >= timeout) {
					uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
					kill(-ud->pid, SIGKILL);
					break;
				}
			}
			// unregister daemon to prevent it from being respawned
			ud->registered = 0;
		}
		ud = ud->next;
	}
}


void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {

	// skip unregistered daemons
	if (!ud->registered) return;

	int throttle = 0;

	if (uwsgi.current_time - ud->last_spawn <= 3) {
		throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
		// if ud->respawns == 0 then we can end up with throttle < 0
		if (throttle <= 0) throttle = 1;
	}

	pid_t pid = uwsgi_fork("uWSGI external daemon");
	if (pid < 0) {
		uwsgi_error("fork()");
		return;
	}

	if (pid > 0) {
		ud->has_daemonized = 0;
		ud->pid = pid;
		ud->status = 1;
		ud->pidfile_checks = 0;
		if (ud->respawns == 0) {
			ud->born = uwsgi_now();
		}

		ud->respawns++;
		ud->last_spawn = uwsgi_now();

	}
	else {
		// close uwsgi sockets
		uwsgi_close_all_sockets();
		uwsgi_close_all_fds();

		if (ud->gid) {
			if (setgid(ud->gid)) {
				uwsgi_error("uwsgi_spawn_daemon()/setgid()");
				exit(1);
			}
		}

		if (ud->uid) {
			if (setuid(ud->uid)) {
				uwsgi_error("uwsgi_spawn_daemon()/setuid()");
				exit(1);
			}
		}

		if (ud->daemonize) {
			/* refork... */
			pid = fork();
			if (pid < 0) {
				uwsgi_error("fork()");
				exit(1);
			}
			if (pid != 0) {
				_exit(0);
			}
			uwsgi_write_pidfile(ud->pidfile);
		}

		if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
			// /dev/null will became stdin
			uwsgi_remap_fd(0, "/dev/null");
		}

		if (setsid() < 0) {
			uwsgi_error("setsid()");
			exit(1);
		}

		if (!ud->pidfile) {
#ifdef __linux__
			if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
				uwsgi_error("prctl()");
			}
#endif
		}


		if (throttle) {
			uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
			sleep((unsigned int) throttle);
		}

		uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid());
		uwsgi_exec_command_with_args(ud->command);
		uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);

		// never here;
		exit(1);
	}

	return;
}


void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {

	struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
	char *pidfile = NULL;
	int daemonize = 0;
	int freq = 10;
	char *space = NULL;
	int stop_signal = SIGTERM;
	int reload_signal = 0;

	char *command = uwsgi_str(value);

#ifdef UWSGI_SSL
	char *legion = NULL;
	if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
		space = strchr(command, ' ');
		if (!space) {
			uwsgi_log("invalid legion daemon syntax: %s\n", command);
			exit(1);
		}
		*space = 0;
		legion = command;
		command = space+1;
	}
#endif

	if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
		space = strchr(command, ' ');
		if (!space) {
			uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
			exit(1);
		}
		*space = 0;
		pidfile = command;
		// check for freq
		char *comma = strchr(pidfile, ',');
		if (comma) {
			*comma = 0;
			freq = atoi(comma + 1);
		}
		command = space + 1;
		if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
			daemonize = 1;
		}
	}

	if (!uwsgi_ud) {
		uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
		uwsgi_ud = uwsgi.daemons;
	}
	else {
		while (uwsgi_ud) {
			old_ud = uwsgi_ud;
			uwsgi_ud = uwsgi_ud->next;
		}

		uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
		old_ud->next = uwsgi_ud;
	}

	uwsgi_ud->command = command;
	uwsgi_ud->pid = 0;
	uwsgi_ud->status = 0;
	uwsgi_ud->freq = freq;
	uwsgi_ud->registered = 0;
	uwsgi_ud->next = NULL;
	uwsgi_ud->respawns = 0;
	uwsgi_ud->last_spawn = 0;
	uwsgi_ud->daemonize = daemonize;
	uwsgi_ud->pidfile = pidfile;
	uwsgi_ud->control = 0;
	uwsgi_ud->stop_signal = stop_signal;
	uwsgi_ud->reload_signal = reload_signal;
	if (!strcmp(opt, "attach-control-daemon")) {
		uwsgi_ud->control = 1;
	}
#ifdef UWSGI_SSL
	uwsgi_ud->legion = legion;
#endif

	uwsgi.daemons_cnt++;

}

void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {

        struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;

	char *d_command = NULL;
	char *d_freq = NULL;
	char *d_pidfile = NULL;
	char *d_control = NULL;
	char *d_legion = NULL;
	char *d_daemonize = NULL;
	char *d_touch = NULL;
	char *d_stopsignal = NULL;
	char *d_reloadsignal = NULL;
	char *d_stdin = NULL;
	char *d_uid = NULL;
	char *d_gid = NULL;

	char *arg = uwsgi_str(value);

	if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
		"command", &d_command,	
		"cmd", &d_command,	
		"exec", &d_command,	
		"freq", &d_freq,	
		"pidfile", &d_pidfile,	
		"control", &d_control,	
		"daemonize", &d_daemonize,	
		"daemon", &d_daemonize,	
		"touch", &d_touch,	
		"stopsignal", &d_stopsignal,	
		"stop_signal", &d_stopsignal,	
		"reloadsignal", &d_reloadsignal,	
		"reload_signal", &d_reloadsignal,	
		"stdin", &d_stdin,	
		"uid", &d_uid,	
		"gid", &d_gid,	
	NULL)) {
		uwsgi_log("invalid --%s keyval syntax\n", opt);
		exit(1);
	}

	if (!d_command) {
		uwsgi_log("--%s: you need to specify a 'command' key\n", opt);
		exit(1);
	}

#ifndef UWSGI_SSL
	if (d_legion) {
		uwsgi_log("legion subsystem is not supported on this uWSGI version, rebuild with ssl support\n");
		exit(1);
	}
#endif



        if (!uwsgi_ud) {
                uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
                uwsgi_ud = uwsgi.daemons;
        }
        else {
                while (uwsgi_ud) {
                        old_ud = uwsgi_ud;
                        uwsgi_ud = uwsgi_ud->next;
                }

                uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
                old_ud->next = uwsgi_ud;
        }
        uwsgi_ud->command = d_command;
        uwsgi_ud->freq = d_freq ? atoi(d_freq) : 10;
        uwsgi_ud->daemonize = d_daemonize ? 1 : 0;
        uwsgi_ud->pidfile = d_pidfile;
        uwsgi_ud->stop_signal = d_stopsignal ? atoi(d_stopsignal) : SIGTERM;
        uwsgi_ud->reload_signal = d_reloadsignal ? atoi(d_reloadsignal) : 0;
        uwsgi_ud->control = d_control ? 1 : 0;
	uwsgi_ud->uid = d_uid ? atoi(d_uid) : 0;
	uwsgi_ud->gid = d_gid ? atoi(d_gid) : 0;
	uwsgi_ud->honour_stdin = d_stdin ? 1 : 0;
#ifdef UWSGI_SSL
        uwsgi_ud->legion = d_legion;
#endif

	if (d_touch) {
		size_t i,rlen = 0;
		char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen);
		for(i=0;i<rlen;i++) {	
			uwsgi_string_new_list(&uwsgi_ud->touch, argv[i]);
		}
		if (argv) free(argv);
	}

        uwsgi.daemons_cnt++;

	free(arg);

}