36 #include <sys/types.h> 45 #include <libxml/xmlmemory.h> 51 using std::ostringstream;
56 #include "ServerApp.h" 57 #include "ServerExitConditions.h" 58 #include "TheBESKeys.h" 60 #include "SocketListener.h" 61 #include "TcpSocket.h" 62 #include "UnixSocket.h" 63 #include "BESServerHandler.h" 65 #include "PPTServer.h" 66 #include "BESMemoryManager.h" 68 #include "BESCatalogUtils.h" 69 #include "BESServerUtils.h" 71 #include "BESDefaultModule.h" 72 #include "BESXMLDefaultCommands.h" 73 #include "BESDaemonConstants.h" 75 static int session_id = 0;
79 static volatile sig_atomic_t sigchild = 0;
80 static volatile sig_atomic_t sigpipe = 0;
81 static volatile sig_atomic_t sigterm = 0;
82 static volatile sig_atomic_t sighup = 0;
86 static volatile int master_listener_pid = -1;
88 static string bes_exit_message(
int cpid,
int stat)
91 oss <<
"beslistener child pid: " << cpid;
92 if (WIFEXITED(stat)) {
93 oss <<
" exited with status: " << WEXITSTATUS(stat);
95 else if (WIFSIGNALED(stat)) {
96 oss <<
" exited with signal: " << WTERMSIG(stat);
98 if (WCOREDUMP(stat)) oss <<
" and a core dump!";
102 oss <<
" exited, but I have no clue as to why";
109 static void block_signals()
113 sigaddset(&
set, SIGCHLD);
114 sigaddset(&
set, SIGHUP);
115 sigaddset(&
set, SIGTERM);
116 sigaddset(&
set, SIGPIPE);
118 if (sigprocmask(SIG_BLOCK, &
set, 0) < 0) {
119 throw BESInternalError(
string(
"sigprocmask error: ") + strerror(errno) +
" while trying to block signals.",
124 static void unblock_signals()
128 sigaddset(&
set, SIGCHLD);
129 sigaddset(&
set, SIGHUP);
130 sigaddset(&
set, SIGTERM);
131 sigaddset(&
set, SIGPIPE);
133 if (sigprocmask(SIG_UNBLOCK, &
set, 0) < 0) {
134 throw BESInternalError(
string(
"sigprocmask error: ") + strerror(errno) +
" while trying to unblock signals.",
146 static void CatchSigChild(
int sig)
148 if (sig == SIGCHLD) {
156 static void CatchSigHup(
int sig)
163 static void CatchSigPipe(
int sig)
165 if (sig == SIGPIPE) {
180 if (getpid() != master_listener_pid) {
181 (*BESLog::TheLog()) <<
"Child listener caught SIGPIPE (master listener PID: " << master_listener_pid
182 <<
"). Child listener Exiting." << endl;
191 signal(sig, SIG_DFL);
203 static void CatchSigTerm(
int sig)
205 if (sig == SIGTERM) {
218 static void register_signal_handlers()
220 struct sigaction act;
221 sigemptyset(&act.sa_mask);
222 sigaddset(&act.sa_mask, SIGCHLD);
223 sigaddset(&act.sa_mask, SIGPIPE);
224 sigaddset(&act.sa_mask, SIGTERM);
225 sigaddset(&act.sa_mask, SIGHUP);
228 BESDEBUG(
"beslistener",
"beslistener: setting restart for sigchld." << endl);
229 act.sa_flags |= SA_RESTART;
232 BESDEBUG(
"beslistener",
"beslistener: Registering signal handlers ... " << endl);
234 act.sa_handler = CatchSigChild;
235 if (sigaction(SIGCHLD, &act, 0))
236 throw BESInternalFatalError(
"Could not register a handler to catch beslistener child process status.", __FILE__,
239 act.sa_handler = CatchSigPipe;
240 if (sigaction(SIGPIPE, &act, 0) < 0)
241 throw BESInternalFatalError(
"Could not register a handler to catch beslistener pipe signal.", __FILE__,
244 act.sa_handler = CatchSigTerm;
245 if (sigaction(SIGTERM, &act, 0) < 0)
246 throw BESInternalFatalError(
"Could not register a handler to catch beslistener terminate signal.", __FILE__,
249 act.sa_handler = CatchSigHup;
250 if (sigaction(SIGHUP, &act, 0) < 0)
251 throw BESInternalFatalError(
"Could not register a handler to catch beslistener hup signal.", __FILE__,
254 BESDEBUG(
"beslistener",
"beslistener: OK" << endl);
257 ServerApp::ServerApp() :
258 BESModuleApp(), _portVal(0), _gotPort(false), _IPVal(
""), _gotIP(false), _unixSocket(
""), _secure(false), _mypid(0), _ts(0), _us(0), _ps(0)
263 ServerApp::~ServerApp()
267 BESCatalogUtils::delete_all_catalogs();
273 bool needhelp =
false;
280 while ((c = getopt(argc, argv,
"hvsd:c:p:u:i:r:H:")) != -1) {
291 _portVal = atoi(optarg);
299 _unixSocket = optarg;
326 if (!dashc.empty()) {
333 if (dashc.empty() && !dashi.empty()) {
334 if (dashi[dashi.length() - 1] !=
'/') {
337 string conf_file = dashi +
"etc/bes/bes.conf";
353 string port_key =
"BES.ServerPort";
362 (*BESLog::TheLog()) << err << endl;
363 exit(SERVER_EXIT_FATAL_CANNOT_START);
366 _portVal = atoi(sPort.c_str());
374 string ip_key =
"BES.ServerIP";
382 (*BESLog::TheLog()) << err << endl;
383 exit(SERVER_EXIT_FATAL_CANNOT_START);
392 string socket_key =
"BES.ServerUnixSocket";
393 if (_unixSocket ==
"") {
400 (*BESLog::TheLog()) << err << endl;
401 exit(SERVER_EXIT_FATAL_CANNOT_START);
405 if (!_gotPort && _unixSocket ==
"") {
406 string msg =
"Must specify a tcp port or a unix socket or both\n";
407 msg +=
"Please specify on the command line with -p <port>";
408 msg +=
" and/or -u <unix_socket>\n";
409 msg +=
"Or specify in the bes configuration file with " + port_key +
" and/or " + socket_key +
"\n";
411 (*BESLog::TheLog()) << msg << endl;
416 if (_secure ==
false) {
417 string key =
"BES.ServerSecure";
425 (*BESLog::TheLog()) << err << endl;
426 exit(SERVER_EXIT_FATAL_CANNOT_START);
428 if (isSecure ==
"Yes" || isSecure ==
"YES" || isSecure ==
"yes") {
433 BESDEBUG(
"beslistener",
"beslistener: initializing default module ... " << endl);
434 BESDefaultModule::initialize(argc, argv);
435 BESDEBUG(
"beslistener",
"beslistener: done initializing default module" << endl);
437 BESDEBUG(
"beslistener",
"beslistener: initializing default commands ... " << endl);
439 BESDEBUG(
"beslistener",
"beslistener: done initializing default commands" << endl);
442 BESDEBUG(
"beslistener",
"beslistener: initializing loaded modules ... " << endl);
444 BESDEBUG(
"beslistener",
"beslistener: done initializing loaded modules" << endl);
446 BESDEBUG(
"beslistener",
"beslistener: initialized settings:" << *
this);
455 session_id = setsid();
456 BESDEBUG(
"beslistener",
"beslistener: The master beslistener session id (group id): " << session_id << endl);
458 master_listener_pid = getpid();
459 BESDEBUG(
"beslistener",
"beslistener: The master beslistener Process id: " << master_listener_pid << endl);
467 BESDEBUG(
"beslistener",
"beslistener: initializing memory pool ... " << endl);
468 BESMemoryManager::initialize_memory_pool();
469 BESDEBUG(
"beslistener",
"OK" << endl);
478 listener.listen(_ts);
480 BESDEBUG(
"beslistener",
"beslistener: listening on port (" << _portVal <<
")" << endl);
486 int status = BESLISTENER_RUNNING;
487 int res = write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
490 (*BESLog::TheLog()) <<
"Master listener could not send status to daemon: " << strerror(errno) << endl;
491 ::exit(SERVER_EXIT_FATAL_CANNOT_START);
495 if (!_unixSocket.empty()) {
497 listener.listen(_us);
498 BESDEBUG(
"beslistener",
"beslistener: listening on unix socket (" << _unixSocket <<
")" << endl);
503 _ps =
new PPTServer(&handler, &listener, _secure);
505 register_signal_handlers();
519 if (sigterm | sighup | sigchild | sigpipe) {
522 while ((cpid = wait4(0 , &stat, WNOHANG, 0)) > 0) {
523 _ps->decr_num_children();
525 (*BESLog::TheLog()) <<
"Master listener caught SISPIPE from child: " << cpid << endl;
529 bes_exit_message(cpid, stat) <<
"; num children: " << _ps->get_num_children() << endl);
534 BESDEBUG(
"ppt2",
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
536 (*BESLog::TheLog()) <<
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl;
537 ::exit(SERVER_EXIT_RESTART);
541 BESDEBUG(
"ppt2",
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
543 (*BESLog::TheLog()) <<
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl;
544 ::exit(SERVER_EXIT_NORMAL_SHUTDOWN);
553 _ps->initConnection();
556 _ps->closeConnection();
559 BESDEBUG(
"beslistener",
"beslistener: caught BESError (" << se.
get_message() <<
")" << endl);
562 int status = SERVER_EXIT_FATAL_CANNOT_START;
563 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
564 close(BESLISTENER_PIPE_FD);
568 (*BESLog::TheLog()) <<
"caught unknown exception initializing sockets" << endl;
569 int status = SERVER_EXIT_FATAL_CANNOT_START;
570 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
571 close(BESLISTENER_PIPE_FD);
575 close(BESLISTENER_PIPE_FD);
581 pid_t apppid = getpid();
582 if (apppid == _mypid) {
585 _ps->closeConnection();
602 BESDEBUG(
"beslistener",
"beslistener: terminating loaded modules ... " << endl);
604 BESDEBUG(
"beslistener",
"beslistener: done terminating loaded modules" << endl);
606 BESDEBUG(
"beslistener",
"beslistener: terminating default commands ... " << endl);
608 BESDEBUG(
"beslistener",
"beslistener: done terminating default commands ... " << endl);
610 BESDEBUG(
"beslistener",
"beslistener: terminating default module ... " << endl);
611 BESDefaultModule::terminate();
612 BESDEBUG(
"beslistener",
"beslistener: done terminating default module ... " << endl);
627 strm << BESIndent::LMarg <<
"ServerApp::dump - (" << (
void *)
this <<
")" << endl;
629 strm << BESIndent::LMarg <<
"got IP? " << _gotIP << endl;
630 strm << BESIndent::LMarg <<
"IP: " << _IPVal << endl;
631 strm << BESIndent::LMarg <<
"got port? " << _gotPort << endl;
632 strm << BESIndent::LMarg <<
"port: " << _portVal << endl;
633 strm << BESIndent::LMarg <<
"unix socket: " << _unixSocket << endl;
634 strm << BESIndent::LMarg <<
"is secure? " << _secure << endl;
635 strm << BESIndent::LMarg <<
"pid: " << _mypid << endl;
637 strm << BESIndent::LMarg <<
"tcp socket:" << endl;
640 BESIndent::UnIndent();
643 strm << BESIndent::LMarg <<
"tcp socket: null" << endl;
646 strm << BESIndent::LMarg <<
"unix socket:" << endl;
649 BESIndent::UnIndent();
652 strm << BESIndent::LMarg <<
"unix socket: null" << endl;
655 strm << BESIndent::LMarg <<
"ppt server:" << endl;
658 BESIndent::UnIndent();
661 strm << BESIndent::LMarg <<
"ppt server: null" << endl;
664 BESIndent::UnIndent();
667 int main(
int argc,
char **argv)
671 return app.
main(argc, argv);
674 cerr <<
"Caught unhandled exception: " << endl;
679 cerr <<
"Caught unhandled, unknown exception" << endl;
exception thrown if an internal error is found and is fatal to the BES
exception thrown if inernal error encountered
static void SetUp(const string &values)
Sets up debugging for the bes.
virtual int main(int argC, char **argV)
main method of the BES application
virtual std::string get_message()
get the error message for this exception
virtual int terminate(int sig=0)
clean up after the application
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.
Abstract exception class for the BES with basic string message.
virtual void dump(ostream &strm) const
dumps information about this object
virtual int terminate(int sig=0)
clean up after the application
virtual void dump(ostream &strm) const
dumps information about this object
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
Base application object for all BES applications.
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
static BESKeys * TheKeys()
static void Register(const string &flagName)
register the specified debug flag
static BESApp * TheApplication(void)
Returns the BESApp application object for this application.
virtual int run()
the applications functionality is implemented in the run method