Created
April 27, 2013 00:54
-
-
Save hanophora/5471424 to your computer and use it in GitHub Desktop.
Programmes de lancement et de contrôle de mon site en FastCGI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <signal.h> | |
char* arg0; | |
void drop_privileges() { | |
if(setreuid(geteuid(), -1) == -1) { | |
perror(arg0); | |
exit(5); | |
} | |
if(setregid(getegid(), -1) == -1) { | |
perror(arg0); | |
exit(5); | |
} | |
} | |
void usage(char *arg0) { | |
printf("Usage: %s stop|restart|pause|resume\n", arg0); | |
} | |
int main(int argc, char** argv) { | |
arg0 = argv[0]; | |
if(argc != 2) { | |
usage(argv[0]); | |
exit(1); | |
} | |
// Oubli de l'uid et du gid réels | |
drop_privileges(); | |
// Récupération du pid | |
char pidstr[10]; | |
FILE* pidfile = fopen("/run/fastcgi/alliance-rainbow.pid", "r"); | |
if(pidfile == NULL) { | |
perror(argv[0]); | |
exit(2); | |
} | |
int nbRead = fread(pidstr, sizeof(char), 9, pidfile); | |
fclose(pidfile); | |
pidstr[nbRead] = '\0'; | |
pid_t pid = (pid_t) strtoimax(pidstr, NULL, 10); | |
// Choix du signal | |
if(strcmp(argv[1], "stop") == 0) { | |
kill(pid, SIGTERM); | |
} | |
else if(strcmp(argv[1], "restart") == 0) { | |
kill(pid, SIGUSR1); | |
} | |
else if(strcmp(argv[1], "pause") == 0) { | |
kill(pid, SIGUSR2); | |
} | |
else if(strcmp(argv[1], "resume") == 0) { | |
kill(pid, SIGCONT); | |
} | |
else { | |
usage(argv[0]); | |
exit(1); | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stddef.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <sys/socket.h> | |
#include <sys/un.h> | |
#include <signal.h> | |
#include <fcntl.h> | |
#include <pwd.h> | |
#include <grp.h> | |
#include <time.h> | |
#include <errno.h> | |
#define UNIX_PATH_MAX 108 | |
char *arg0; | |
int shutdowning = 0; | |
int pidMain = -1, pidAjax = -1; | |
/* ---------- Fonctions d'initialisation ---------- */ | |
void drop_privileges() { | |
if(setreuid(geteuid(), -1) == -1) { | |
perror(arg0); | |
exit(5); | |
} | |
if(setregid(getegid(), -1) == -1) { | |
perror(arg0); | |
exit(5); | |
} | |
} | |
void daemonize() { | |
if(daemon(1, 1) == -1) { | |
perror(arg0); | |
exit(6); | |
} | |
} | |
void mkPidfile() { | |
FILE *pidfile = fopen("/run/fastcgi/alliance-rainbow.pid", "w"); | |
if(!pidfile) { | |
perror(arg0); | |
exit(7); | |
} | |
fprintf(pidfile, "%d", getpid()); | |
fclose(pidfile); | |
} | |
void rmPidfile() { | |
unlink("/run/fastcgi/alliance-rainbow.pid"); | |
} | |
int openSocket(char *path) { | |
int pathlen = strlen(path); | |
if(pathlen + 1 > UNIX_PATH_MAX) { | |
fprintf(stderr, "Nom de socket trop long\n"); | |
exit(7); | |
} | |
int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
struct sockaddr_un addr; | |
addr.sun_family = AF_UNIX; | |
strncpy(addr.sun_path, path, UNIX_PATH_MAX); | |
int len = offsetof(struct sockaddr_un, sun_path) + pathlen + 1; | |
unlink(path); | |
if(bind(fd, (struct sockaddr*)&addr, len) == -1) { | |
perror(arg0); | |
exit(8); | |
} | |
if(listen(fd, 20) == -1) { | |
perror(arg0); | |
exit(8); | |
} | |
chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); | |
return fd; | |
} | |
void closeSocket(int fd, char *path) { | |
close(fd); | |
unlink(path); | |
} | |
/* ------------- Fonction de lancement ------------ */ | |
pid_t spawn(char *path, int sock) { | |
pid_t pid = fork(); | |
if(pid == -1) { | |
perror(arg0); | |
exit(9); | |
} | |
if(pid != 0) { | |
return pid; | |
} | |
dup2(sock, STDIN_FILENO); | |
execl(path, path, (char*)NULL); | |
perror(path); | |
exit(9); | |
} | |
void msg(char *msg) { | |
time_t tim = time(NULL); | |
struct tm *loc_tim = localtime(&tim); | |
char dat[18]; | |
if(strftime(dat, 18, "%d/%m/%y %H:%M:%S", loc_tim) == 0) { | |
dat[0] = '\0'; | |
} | |
printf("[%s] %s\n", dat, msg); | |
} | |
/* ------------ Gestionnaires de signal ----------- */ | |
void init_shutdown(int sig) { | |
msg("Shutdown"); | |
shutdowning = 1; | |
if(pidMain > 0) kill(pidMain, SIGUSR1); | |
if(pidAjax > 0) kill(pidAjax, SIGUSR1); | |
} | |
void restart(int sig) { | |
msg("Restart"); | |
if(pidMain > 0) kill(pidMain, SIGUSR1); | |
if(pidAjax > 0) kill(pidAjax, SIGUSR1); | |
} | |
void enter_pause(int sig) { | |
msg("Pause"); | |
sigset_t set; | |
sigemptyset(&set); | |
sigaddset(&set, SIGCHLD); | |
sigprocmask(SIG_SETMASK, &set, NULL); | |
if(pidMain > 0) { | |
kill(pidMain, SIGUSR1); | |
} | |
if(pidAjax > 0) { | |
kill(pidAjax, SIGUSR1); | |
} | |
sigsuspend(&set); | |
msg("Resume"); | |
sigemptyset(&set); | |
sigprocmask(SIG_SETMASK, &set, NULL); | |
} | |
void resume(int sig) { | |
} | |
void register_signals() { | |
struct sigaction act; | |
sigset_t set; | |
sigemptyset(&set); | |
act.sa_mask = set; | |
act.sa_flags = 0; | |
act.sa_handler = init_shutdown; | |
sigaction(SIGTERM, &act, NULL); | |
sigaction(SIGINT, &act, NULL); | |
act.sa_handler = restart; | |
sigaction(SIGUSR1, &act, NULL); | |
act.sa_handler = enter_pause; | |
sigaction(SIGUSR2, &act, NULL); | |
act.sa_handler = resume; | |
sigaction(SIGCONT, &act, NULL); | |
} | |
/* ------------------------------------------------ */ | |
int main(int argc, char** argv) { | |
arg0 = argv[0]; | |
// Initialisation | |
drop_privileges(); | |
daemonize(); | |
mkPidfile(); | |
register_signals(); | |
fcntl(STDOUT_FILENO, F_SETFD, FD_CLOEXEC); | |
fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC); | |
// Création des sockets | |
int sockMain = openSocket("/run/fastcgi/alliance-rainbow.main.sock"); | |
time_t timeMain = time(NULL); | |
int nbDeathsMain = 0; | |
int sockAjax = openSocket("/run/fastcgi/alliance-rainbow.ajax.sock"); | |
time_t timeAjax = time(NULL); | |
int nbDeathsAjax = 0; | |
// Premier lancement | |
pidMain = spawn("./main.rb", sockMain); | |
pidAjax = spawn("./ajax.rb", sockAjax); | |
// Boucle principale | |
while(pidMain != -1 || pidAjax != -1) { | |
pid_t proc = wait(NULL); | |
time_t curTime = time(NULL); | |
if(proc == pidMain) { | |
pidMain = -1; | |
if(!shutdowning) { | |
msg("Main est mort, longue vie à Main !"); | |
if(curTime - timeMain <= 10) { | |
nbDeathsMain++; | |
if(nbDeathsMain == 3) { | |
msg("Main meurt trop vite, mise en pause"); | |
enter_pause(SIGUSR2); | |
} | |
} | |
else { | |
timeMain = curTime; | |
nbDeathsMain = 1; | |
} | |
pidMain = spawn("./main.rb", sockMain); | |
} | |
} | |
else if(proc == pidAjax) { | |
pidAjax = -1; | |
if(!shutdowning) { | |
msg("Ajax est mort, longue vie à Ajax !"); | |
if(curTime - timeAjax <= 10) { | |
nbDeathsAjax++; | |
if(nbDeathsAjax == 3) { | |
msg("Ajax meurt trop vite, désactivation de ce worker"); | |
continue; | |
} | |
} | |
else { | |
timeAjax = curTime; | |
nbDeathsAjax = 1; | |
} | |
pidAjax = spawn("./ajax.rb", sockAjax); | |
} | |
} | |
} | |
// Désinitialisation | |
closeSocket(sockMain, "/run/fastcgi/alliance-rainbow.main.sock"); | |
closeSocket(sockAjax, "/run/fastcgi/alliance-rainbow.ajax.sock"); | |
rmPidfile(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment