38 #include <sys/types.h>
47 #include <libxml/xmlmemory.h>
53 using std::ostringstream;
58 #include "ServerApp.h"
59 #include "ServerExitConditions.h"
60 #include "TheBESKeys.h"
62 #include "SocketListener.h"
63 #include "TcpSocket.h"
64 #include "UnixSocket.h"
65 #include "BESServerHandler.h"
67 #include "PPTServer.h"
68 #include "BESMemoryManager.h"
70 #include "BESCatalogUtils.h"
71 #include "BESServerUtils.h"
73 #include "BESDefaultModule.h"
74 #include "BESXMLDefaultCommands.h"
75 #include "BESDaemonConstants.h"
77 static int session_id = 0;
81 static volatile sig_atomic_t sigchild = 0;
82 static volatile sig_atomic_t sigpipe = 0;
83 static volatile sig_atomic_t sigterm = 0;
84 static volatile sig_atomic_t sighup = 0;
88 static volatile int master_listener_pid = -1;
90 static string bes_exit_message(
int cpid,
int stat)
93 oss <<
"beslistener child pid: " << cpid;
94 if (WIFEXITED(stat)) {
95 oss <<
" exited with status: " << WEXITSTATUS(stat);
97 else if (WIFSIGNALED(stat)) {
98 oss <<
" exited with signal: " << WTERMSIG(stat);
100 if (WCOREDUMP(stat)) oss <<
" and a core dump!";
104 oss <<
" exited, but I have no clue as to why";
111 static void block_signals()
115 sigaddset(&set, SIGCHLD);
116 sigaddset(&set, SIGHUP);
117 sigaddset(&set, SIGTERM);
118 sigaddset(&set, SIGPIPE);
120 if (sigprocmask(SIG_BLOCK, &set, 0) < 0) {
121 throw BESInternalError(
string(
"sigprocmask error: ") + strerror(errno) +
" while trying to block signals.",
126 static void unblock_signals()
130 sigaddset(&set, SIGCHLD);
131 sigaddset(&set, SIGHUP);
132 sigaddset(&set, SIGTERM);
133 sigaddset(&set, SIGPIPE);
135 if (sigprocmask(SIG_UNBLOCK, &set, 0) < 0) {
136 throw BESInternalError(
string(
"sigprocmask error: ") + strerror(errno) +
" while trying to unblock signals.",
148 static void CatchSigChild(
int sig)
150 if (sig == SIGCHLD) {
158 static void CatchSigHup(
int sig)
165 static void CatchSigPipe(
int sig)
167 if (sig == SIGPIPE) {
182 if (getpid() != master_listener_pid) {
183 INFO_LOG(
"Child listener (PID: " << getpid() <<
") caught SIGPIPE (master listener PID: "
184 << master_listener_pid <<
"). Child listener Exiting." << endl);
193 signal(sig, SIG_DFL);
197 INFO_LOG(
"Master listener (PID: " << getpid() <<
") caught SIGPIPE." << endl);
207 static void CatchSigTerm(
int sig)
209 if (sig == SIGTERM) {
222 static void register_signal_handlers()
224 struct sigaction act;
225 sigemptyset(&act.sa_mask);
226 sigaddset(&act.sa_mask, SIGCHLD);
227 sigaddset(&act.sa_mask, SIGPIPE);
228 sigaddset(&act.sa_mask, SIGTERM);
229 sigaddset(&act.sa_mask, SIGHUP);
232 BESDEBUG(
"beslistener",
"beslistener: setting restart for sigchld." << endl);
233 act.sa_flags |= SA_RESTART;
236 BESDEBUG(
"beslistener",
"beslistener: Registering signal handlers ... " << endl);
238 act.sa_handler = CatchSigChild;
239 if (sigaction(SIGCHLD, &act, 0))
240 throw BESInternalFatalError(
"Could not register a handler to catch beslistener child process status.", __FILE__,
243 act.sa_handler = CatchSigPipe;
244 if (sigaction(SIGPIPE, &act, 0) < 0)
245 throw BESInternalFatalError(
"Could not register a handler to catch beslistener pipe signal.", __FILE__,
248 act.sa_handler = CatchSigTerm;
249 if (sigaction(SIGTERM, &act, 0) < 0)
250 throw BESInternalFatalError(
"Could not register a handler to catch beslistener terminate signal.", __FILE__,
253 act.sa_handler = CatchSigHup;
254 if (sigaction(SIGHUP, &act, 0) < 0)
255 throw BESInternalFatalError(
"Could not register a handler to catch beslistener hup signal.", __FILE__,
258 BESDEBUG(
"beslistener",
"beslistener: OK" << endl);
261 ServerApp::ServerApp() :
262 BESModuleApp(), _portVal(0), _gotPort(false), _IPVal(
""), _gotIP(false), _unixSocket(
""), _secure(false), _mypid(0), _ts(0), _us(0), _ps(0)
267 ServerApp::~ServerApp()
272 BESCatalogUtils::delete_all_catalogs();
280 bool needhelp =
false;
287 while ((c = getopt(argc, argv,
"hvsd:c:p:u:i:r:H:")) != -1) {
298 _portVal = atoi(optarg);
306 _unixSocket = optarg;
333 if (!dashc.empty()) {
340 if (dashc.empty() && !dashi.empty()) {
341 if (dashi[dashi.length() - 1] !=
'/') {
344 string conf_file = dashi +
"etc/bes/bes.conf";
360 string port_key =
"BES.ServerPort";
369 ERROR_LOG(err << endl);
370 exit(SERVER_EXIT_FATAL_CANNOT_START);
373 _portVal = atoi(sPort.c_str());
381 string ip_key =
"BES.ServerIP";
389 ERROR_LOG(err << endl);
390 exit(SERVER_EXIT_FATAL_CANNOT_START);
399 string socket_key =
"BES.ServerUnixSocket";
400 if (_unixSocket ==
"") {
407 ERROR_LOG(err << endl);
408 exit(SERVER_EXIT_FATAL_CANNOT_START);
412 if (!_gotPort && _unixSocket ==
"") {
413 string msg =
"Must specify a tcp port or a unix socket or both\n";
414 msg +=
"Please specify on the command line with -p <port>";
415 msg +=
" and/or -u <unix_socket>\n";
416 msg +=
"Or specify in the bes configuration file with " + port_key +
" and/or " + socket_key +
"\n";
418 ERROR_LOG(msg << endl);
423 if (_secure ==
false) {
424 string key =
"BES.ServerSecure";
432 ERROR_LOG(err << endl);
433 exit(SERVER_EXIT_FATAL_CANNOT_START);
435 if (isSecure ==
"Yes" || isSecure ==
"YES" || isSecure ==
"yes") {
440 BESDEBUG(
"beslistener",
"beslistener: initializing default module ... " << endl);
441 BESDefaultModule::initialize(argc, argv);
442 BESDEBUG(
"beslistener",
"beslistener: done initializing default module" << endl);
444 BESDEBUG(
"beslistener",
"beslistener: initializing default commands ... " << endl);
446 BESDEBUG(
"beslistener",
"beslistener: done initializing default commands" << endl);
449 BESDEBUG(
"beslistener",
"beslistener: initializing loaded modules ... " << endl);
451 BESDEBUG(
"beslistener",
"beslistener: done initializing loaded modules" << endl);
453 BESDEBUG(
"beslistener",
"beslistener: initialized settings:" << *
this);
462 session_id = setsid();
463 BESDEBUG(
"beslistener",
"beslistener: The master beslistener session id (group id): " << session_id << endl);
465 master_listener_pid = getpid();
466 BESDEBUG(
"beslistener",
"beslistener: The master beslistener Process id: " << master_listener_pid << endl);
474 BESDEBUG(
"beslistener",
"beslistener: initializing memory pool ... " << endl);
475 BESMemoryManager::initialize_memory_pool();
476 BESDEBUG(
"beslistener",
"OK" << endl);
485 listener.listen(_ts);
487 BESDEBUG(
"beslistener",
"beslistener: listening on port (" << _portVal <<
")" << endl);
493 int status = BESLISTENER_RUNNING;
494 int res = write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
497 ERROR_LOG(
"Master listener could not send status to daemon: " << strerror(errno) << endl);
498 ::exit(SERVER_EXIT_FATAL_CANNOT_START);
502 if (!_unixSocket.empty()) {
504 listener.listen(_us);
505 BESDEBUG(
"beslistener",
"beslistener: listening on unix socket (" << _unixSocket <<
")" << endl);
510 _ps =
new PPTServer(&handler, &listener, _secure);
512 register_signal_handlers();
526 if (sigterm | sighup | sigchild | sigpipe) {
529 while ((cpid = wait4(0 , &stat, WNOHANG, 0)) > 0) {
530 _ps->decr_num_children();
532 INFO_LOG(
"Master listener caught SISPIPE from child: " << cpid << endl);
536 bes_exit_message(cpid, stat) <<
"; num children: " << _ps->get_num_children() << endl);
541 BESDEBUG(
"ppt2",
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
543 INFO_LOG(
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
544 ::exit(SERVER_EXIT_RESTART);
548 BESDEBUG(
"ppt2",
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
550 INFO_LOG(
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
551 ::exit(SERVER_EXIT_NORMAL_SHUTDOWN);
565 _ps->closeConnection();
568 BESDEBUG(
"beslistener",
"beslistener: caught BESError (" << se.
get_message() <<
")" << endl);
571 int status = SERVER_EXIT_FATAL_CANNOT_START;
572 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
573 close(BESLISTENER_PIPE_FD);
577 ERROR_LOG(
"caught unknown exception initializing sockets" << endl);
578 int status = SERVER_EXIT_FATAL_CANNOT_START;
579 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
580 close(BESLISTENER_PIPE_FD);
584 close(BESLISTENER_PIPE_FD);
590 pid_t apppid = getpid();
591 if (apppid == _mypid) {
594 _ps->closeConnection();
611 BESDEBUG(
"beslistener",
"beslistener: terminating loaded modules ... " << endl);
613 BESDEBUG(
"beslistener",
"beslistener: done terminating loaded modules" << endl);
615 BESDEBUG(
"beslistener",
"beslistener: terminating default commands ... " << endl);
617 BESDEBUG(
"beslistener",
"beslistener: done terminating default commands ... " << endl);
619 BESDEBUG(
"beslistener",
"beslistener: terminating default module ... " << endl);
620 BESDefaultModule::terminate();
621 BESDEBUG(
"beslistener",
"beslistener: done terminating default module ... " << endl);
636 strm << BESIndent::LMarg <<
"ServerApp::dump - (" << (
void *)
this <<
")" << endl;
638 strm << BESIndent::LMarg <<
"got IP? " << _gotIP << endl;
639 strm << BESIndent::LMarg <<
"IP: " << _IPVal << endl;
640 strm << BESIndent::LMarg <<
"got port? " << _gotPort << endl;
641 strm << BESIndent::LMarg <<
"port: " << _portVal << endl;
642 strm << BESIndent::LMarg <<
"unix socket: " << _unixSocket << endl;
643 strm << BESIndent::LMarg <<
"is secure? " << _secure << endl;
644 strm << BESIndent::LMarg <<
"pid: " << _mypid << endl;
646 strm << BESIndent::LMarg <<
"tcp socket:" << endl;
649 BESIndent::UnIndent();
652 strm << BESIndent::LMarg <<
"tcp socket: null" << endl;
655 strm << BESIndent::LMarg <<
"unix socket:" << endl;
658 BESIndent::UnIndent();
661 strm << BESIndent::LMarg <<
"unix socket: null" << endl;
664 strm << BESIndent::LMarg <<
"ppt server:" << endl;
667 BESIndent::UnIndent();
670 strm << BESIndent::LMarg <<
"ppt server: null" << endl;
673 BESIndent::UnIndent();
676 int main(
int argc,
char **argv)
680 return app.
main(argc, argv);
683 cerr <<
"Caught unhandled exception: " << endl;
688 cerr <<
"Caught unhandled, unknown exception" << endl;
static BESApp * TheApplication(void)
Returns the BESApp application object for this application.
std::string appName(void) const
Returns the name of the application.
virtual int main(int argC, char **argV)
main routine, the main entry point for any BES applications.
static void SetUp(const std::string &values)
Sets up debugging for the bes.
static void Register(const std::string &flagName)
register the specified debug flag
Abstract exception class for the BES with basic string message.
virtual std::string get_message()
get the error message for this exception
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
Base application object for all BES applications.
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual int terminate(int sig=0)
clean up after the application
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
static int terminate(void)
Removes the default set of BES XML commands from the list of possible commands.
static int initialize(int argc, char **argv)
Loads the default set of BES XML commands.
virtual void initConnection()
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual int terminate(int sig=0)
clean up after the application
virtual int run()
The body of the application, implementing the primary functionality of the BES application.
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
virtual void dump(std::ostream &strm) const
dumps information about this object
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
static std::string ConfigFile
virtual void dump(std::ostream &strm) const
dumps information about this object