/* WebROaR - Ruby Application Server - http://webroar.in/
* Copyright (C) 2009 WebROaR
*
* This file is part of WebROaR.
*
* WebROaR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* WebROaR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WebROaR. If not, see .
*/
#include
#include
#include
#include
// wr_server object
static wr_svr_t *server;
/** Cleanup and destroy the Server */
static inline void cleanup(wr_svr_t *server) {
LOG_FUNCTION
// Delete 'webroar.sock' file
remove(WR_TMP_SOCK_FILE);
// Stop event loop
ev_unloop(server->ebb_svr.loop, EVUNLOOP_ALL);
// Destroy the Server structure
wr_svr_free(server);
// Delete 'webroar.pid' file
remove(WR_PID_FILE);
LOG_INFO("Shutting down network server. No more request can be served");
// Destroy logger object
close_logger();
}
/** Daemonize the process */
static inline void daemonize() {
LOG_FUNCTION
/* Our process ID and Session ID */
pid_t pid, sid;
pid_t saved_pid = -1;
if(saved_pid > 0) {
printf("SERVER IS ALREADY RUNNING WITH PID %i",saved_pid);
exit(-1);
}
LOG_DEBUG(4,"Calling fork");
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* Open any logs here */
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
/* Log the failure */
exit(EXIT_FAILURE);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
int i=open("/dev/null",O_RDWR); /* open stdin and connect to /dev/null */
LOG_DEBUG(DEBUG,"i=%d",i);
int j = dup(i); /* stdout */
LOG_DEBUG(DEBUG,"j=%d",j);
j = dup(i); /* stderr */
LOG_DEBUG(DEBUG,"j=%d",j);
//Log current pid
char str[WR_SHORT_STR_LEN];
int pid_FD=open(WR_PID_FILE,O_RDWR|O_CREAT,0640);
LOG_DEBUG(4,"FD for PID is %i",pid_FD);
if (pid_FD<0) {
LOG_ERROR(5,"CANNOT OPEN PID FILE:%s",strerror(errno));
exit(1); /* can not open */
}
int lpk = lockf(pid_FD,F_TLOCK,0);
if (lpk<0) {
printf("SERVER ALREADY RUNNING..\n");
//can not lock
exit(-1);
}
/* first instance continues */
sprintf(str,"%d\n",getpid());
int x = write(pid_FD,str,strlen(str)); /* record pid to lockfile */
close(pid_FD);
signal(SIGCHLD, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
/* Close out the standard file descriptors */
LOG_DEBUG(4,"Daemonize Server Done");
}
/** Handle interrupt signal */
void sigproc() {
LOG_DEBUG(4,"**************Caught Interrupt Signal************");
// lear keep alive flag.
server->is_running = 0;
}
int main(int argc, char *argv[]) {
int retval = 0;
wr_conf_t *conf=NULL;
char *WR_ROOT = argv[1];
//Initialize logger
if(initialize_logger(WR_LOG_FILE) == 0) {
LOG_DEBUG(DEBUG,"Logging started in %s file",WR_LOG_FILE);
} else {
printf("Logger initialization failed. Please make sure you have write permission on '/var/log/webroar' directory.");
}
//Allocate and initialize configuration structure
conf = wr_conf_read(WR_ROOT);
if(conf == NULL ) {
LOG_ERROR(FATAL,"Configuration reading failed.");
printf("Server not started.\nProblem with reading the configuration file. Kindly refer the log files for details.\n");
return -1;
}
#ifdef L_DEBUG
set_log_severity(DEBUG);
#else
set_log_severity(conf->server->log_level);
#endif
// Add Admin Panel
wr_conf_admin_panel_add(conf);
//TODO: Windows Portability?
signal(SIGINT, sigproc);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP,sigproc); /* catch hangup signal */
signal(SIGTERM,sigproc); /* catch terminate signal */
// Initialize and start the Server to accept requests
retval = wr_svr_init(&server, conf);
if(retval<0) {
LOG_ERROR(FATAL,"Initialization of network server failed.");
printf("Server not started. Kindly refer the log files for details.\n");
return retval;
}
LOG_INFO("Network server successfully initialized on port %d",server->conf->server->port);
// Set keep alive flag
server->is_running = 1;
// Initialize contol port/sock path to recive control messages
retval = wr_ctl_init(server);
if(retval < 0) {
LOG_ERROR(FATAL,"Controller Initialization failed.");
printf("Server not started. Kindly refer the log files for details.\n");
wr_svr_free(server);
return retval;
}
LOG_INFO("Controller initialized");
// Fork processes and start 'webroar-workers's
wr_app_init(server);
//Daemonize the Server
daemonize();
LOG_DEBUG(4,"Done daemon");
// Start event loop
while(server->is_running) {
ev_loop(server->ebb_svr.loop,EVLOOP_ONESHOT);
}
// Cleanup
LOG_DEBUG(DEBUG,"Call cleanup");
cleanup(server);
return 0;
}