mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-06-16 02:15:48 +00:00
197 lines
4.6 KiB
C
197 lines
4.6 KiB
C
#include "uwsgi.h"
|
|
|
|
extern struct uwsgi_server uwsgi;
|
|
|
|
struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), void *data) {
|
|
|
|
struct uwsgi_gateway *ug;
|
|
int num = 1, i;
|
|
|
|
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
|
|
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < ushared->gateways_cnt; i++) {
|
|
if (!strcmp(name, ushared->gateways[i].name)) {
|
|
num++;
|
|
}
|
|
}
|
|
|
|
char *str = uwsgi_num2str(num);
|
|
char *fullname = uwsgi_concat3(name, " ", str);
|
|
free(str);
|
|
|
|
ug = &ushared->gateways[ushared->gateways_cnt];
|
|
ug->pid = 0;
|
|
ug->name = name;
|
|
ug->loop = loop;
|
|
ug->num = num;
|
|
ug->fullname = fullname;
|
|
ug->data = data;
|
|
ug->uid = 0;
|
|
ug->gid = 0;
|
|
|
|
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
|
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
|
|
#else
|
|
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
|
|
#endif
|
|
uwsgi_error("socketpair()");
|
|
}
|
|
|
|
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
|
|
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
|
|
|
|
if (!uwsgi.master_process && !uwsgi.force_gateway)
|
|
gateway_respawn(ushared->gateways_cnt);
|
|
|
|
ushared->gateways_cnt++;
|
|
|
|
|
|
return ug;
|
|
}
|
|
|
|
static void gateway_brutal_end() {
|
|
_exit(UWSGI_END_CODE);
|
|
}
|
|
|
|
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);
|
|
uwsgi_close_all_unshared_sockets();
|
|
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);
|
|
|
|
uwsgi_hooks_run(uwsgi.hook_as_gateway, "as-gateway", 1);
|
|
|
|
if (ug->gid) {
|
|
uwsgi_log("%s %d setgid() to %d\n", ug->name, ug->num, (int) ug->gid);
|
|
if (setgid(ug->gid)) {
|
|
uwsgi_error("gateway_respawn()/setgid()");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (ug->uid) {
|
|
uwsgi_log("%s %d setuid() to %d\n", ug->name, ug->num, (int) ug->uid);
|
|
if (setuid(ug->uid)) {
|
|
uwsgi_error("gateway_respawn()/setuid()");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
}
|
|
|
|
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
|
|
|
|
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
|
|
|
|
if (!uwsgi_sock) {
|
|
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
|
uwsgi_sock = uwsgi.gateway_sockets;
|
|
}
|
|
else {
|
|
while (uwsgi_sock) {
|
|
old_uwsgi_sock = uwsgi_sock;
|
|
uwsgi_sock = uwsgi_sock->next;
|
|
}
|
|
|
|
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
|
old_uwsgi_sock->next = uwsgi_sock;
|
|
}
|
|
|
|
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
|
|
uwsgi_sock->fd = -1;
|
|
uwsgi_sock->shared = 0;
|
|
uwsgi_sock->name = name;
|
|
uwsgi_sock->name_len = strlen(name);
|
|
uwsgi_sock->owner = owner;
|
|
|
|
return uwsgi_sock;
|
|
}
|
|
|
|
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int fd, char *owner) {
|
|
|
|
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
|
|
|
|
if (!uwsgi_sock) {
|
|
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
|
uwsgi_sock = uwsgi.gateway_sockets;
|
|
}
|
|
else {
|
|
while (uwsgi_sock) {
|
|
old_uwsgi_sock = uwsgi_sock;
|
|
uwsgi_sock = uwsgi_sock->next;
|
|
}
|
|
|
|
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
|
old_uwsgi_sock->next = uwsgi_sock;
|
|
}
|
|
|
|
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
|
|
uwsgi_sock->fd = fd;
|
|
uwsgi_sock->name = uwsgi_getsockname(fd);
|
|
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
|
|
uwsgi_sock->owner = owner;
|
|
|
|
return uwsgi_sock;
|
|
}
|
|
|
|
|
|
void uwsgi_gateway_go_cheap(char *gw_id, int queue, int *i_am_cheap) {
|
|
|
|
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
|
|
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
|
while (ugs) {
|
|
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
|
|
event_queue_del_fd(queue, ugs->fd, event_queue_read());
|
|
}
|
|
ugs = ugs->next;
|
|
}
|
|
*i_am_cheap = 1;
|
|
}
|