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 (PID: " << getpid() <<
") caught SIGPIPE (master listener PID: " 182 << master_listener_pid <<
"). Child listener Exiting." << endl;
191 signal(sig, SIG_DFL);
195 LOG(
"Master listener (PID: " << getpid() <<
") caught SIGPIPE." << endl);
205 static void CatchSigTerm(
int sig)
207 if (sig == SIGTERM) {
220 static void register_signal_handlers()
222 struct sigaction act;
223 sigemptyset(&act.sa_mask);
224 sigaddset(&act.sa_mask, SIGCHLD);
225 sigaddset(&act.sa_mask, SIGPIPE);
226 sigaddset(&act.sa_mask, SIGTERM);
227 sigaddset(&act.sa_mask, SIGHUP);
230 BESDEBUG(
"beslistener",
"beslistener: setting restart for sigchld." << endl);
231 act.sa_flags |= SA_RESTART;
234 BESDEBUG(
"beslistener",
"beslistener: Registering signal handlers ... " << endl);
236 act.sa_handler = CatchSigChild;
237 if (sigaction(SIGCHLD, &act, 0))
238 throw BESInternalFatalError(
"Could not register a handler to catch beslistener child process status.", __FILE__,
241 act.sa_handler = CatchSigPipe;
242 if (sigaction(SIGPIPE, &act, 0) < 0)
243 throw BESInternalFatalError(
"Could not register a handler to catch beslistener pipe signal.", __FILE__,
246 act.sa_handler = CatchSigTerm;
247 if (sigaction(SIGTERM, &act, 0) < 0)
248 throw BESInternalFatalError(
"Could not register a handler to catch beslistener terminate signal.", __FILE__,
251 act.sa_handler = CatchSigHup;
252 if (sigaction(SIGHUP, &act, 0) < 0)
253 throw BESInternalFatalError(
"Could not register a handler to catch beslistener hup signal.", __FILE__,
256 BESDEBUG(
"beslistener",
"beslistener: OK" << endl);
259 ServerApp::ServerApp() :
260 BESModuleApp(), _portVal(0), _gotPort(false), _IPVal(
""), _gotIP(false), _unixSocket(
""), _secure(false), _mypid(0), _ts(0), _us(0), _ps(0)
265 ServerApp::~ServerApp()
269 BESCatalogUtils::delete_all_catalogs();
275 bool needhelp =
false;
282 while ((c = getopt(argc, argv,
"hvsd:c:p:u:i:r:H:")) != -1) {
293 _portVal = atoi(optarg);
301 _unixSocket = optarg;
328 if (!dashc.empty()) {
335 if (dashc.empty() && !dashi.empty()) {
336 if (dashi[dashi.length() - 1] !=
'/') {
339 string conf_file = dashi +
"etc/bes/bes.conf";
355 string port_key =
"BES.ServerPort";
365 exit(SERVER_EXIT_FATAL_CANNOT_START);
368 _portVal = atoi(sPort.c_str());
376 string ip_key =
"BES.ServerIP";
385 exit(SERVER_EXIT_FATAL_CANNOT_START);
394 string socket_key =
"BES.ServerUnixSocket";
395 if (_unixSocket ==
"") {
403 exit(SERVER_EXIT_FATAL_CANNOT_START);
407 if (!_gotPort && _unixSocket ==
"") {
408 string msg =
"Must specify a tcp port or a unix socket or both\n";
409 msg +=
"Please specify on the command line with -p <port>";
410 msg +=
" and/or -u <unix_socket>\n";
411 msg +=
"Or specify in the bes configuration file with " + port_key +
" and/or " + socket_key +
"\n";
418 if (_secure ==
false) {
419 string key =
"BES.ServerSecure";
428 exit(SERVER_EXIT_FATAL_CANNOT_START);
430 if (isSecure ==
"Yes" || isSecure ==
"YES" || isSecure ==
"yes") {
435 BESDEBUG(
"beslistener",
"beslistener: initializing default module ... " << endl);
436 BESDefaultModule::initialize(argc, argv);
437 BESDEBUG(
"beslistener",
"beslistener: done initializing default module" << endl);
439 BESDEBUG(
"beslistener",
"beslistener: initializing default commands ... " << endl);
441 BESDEBUG(
"beslistener",
"beslistener: done initializing default commands" << endl);
444 BESDEBUG(
"beslistener",
"beslistener: initializing loaded modules ... " << endl);
446 BESDEBUG(
"beslistener",
"beslistener: done initializing loaded modules" << endl);
448 BESDEBUG(
"beslistener",
"beslistener: initialized settings:" << *
this);
457 session_id = setsid();
458 BESDEBUG(
"beslistener",
"beslistener: The master beslistener session id (group id): " << session_id << endl);
460 master_listener_pid = getpid();
461 BESDEBUG(
"beslistener",
"beslistener: The master beslistener Process id: " << master_listener_pid << endl);
469 BESDEBUG(
"beslistener",
"beslistener: initializing memory pool ... " << endl);
470 BESMemoryManager::initialize_memory_pool();
471 BESDEBUG(
"beslistener",
"OK" << endl);
480 listener.listen(_ts);
482 BESDEBUG(
"beslistener",
"beslistener: listening on port (" << _portVal <<
")" << endl);
488 int status = BESLISTENER_RUNNING;
489 int res = write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
492 LOG(
"Master listener could not send status to daemon: " << strerror(errno) << endl);
493 ::exit(SERVER_EXIT_FATAL_CANNOT_START);
497 if (!_unixSocket.empty()) {
499 listener.listen(_us);
500 BESDEBUG(
"beslistener",
"beslistener: listening on unix socket (" << _unixSocket <<
")" << endl);
505 _ps =
new PPTServer(&handler, &listener, _secure);
507 register_signal_handlers();
521 if (sigterm | sighup | sigchild | sigpipe) {
524 while ((cpid = wait4(0 , &stat, WNOHANG, 0)) > 0) {
525 _ps->decr_num_children();
527 LOG(
"Master listener caught SISPIPE from child: " << cpid << endl);
531 bes_exit_message(cpid, stat) <<
"; num children: " << _ps->get_num_children() << endl);
536 BESDEBUG(
"ppt2",
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
538 LOG(
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
539 ::exit(SERVER_EXIT_RESTART);
543 BESDEBUG(
"ppt2",
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
545 LOG(
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
546 ::exit(SERVER_EXIT_NORMAL_SHUTDOWN);
555 _ps->initConnection();
558 _ps->closeConnection();
561 BESDEBUG(
"beslistener",
"beslistener: caught BESError (" << se.
get_message() <<
")" << endl);
564 int status = SERVER_EXIT_FATAL_CANNOT_START;
565 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
566 close(BESLISTENER_PIPE_FD);
570 LOG(
"caught unknown exception initializing sockets" << endl);
571 int status = SERVER_EXIT_FATAL_CANNOT_START;
572 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
573 close(BESLISTENER_PIPE_FD);
577 close(BESLISTENER_PIPE_FD);
583 pid_t apppid = getpid();
584 if (apppid == _mypid) {
587 _ps->closeConnection();
604 BESDEBUG(
"beslistener",
"beslistener: terminating loaded modules ... " << endl);
606 BESDEBUG(
"beslistener",
"beslistener: done terminating loaded modules" << endl);
608 BESDEBUG(
"beslistener",
"beslistener: terminating default commands ... " << endl);
610 BESDEBUG(
"beslistener",
"beslistener: done terminating default commands ... " << endl);
612 BESDEBUG(
"beslistener",
"beslistener: terminating default module ... " << endl);
613 BESDefaultModule::terminate();
614 BESDEBUG(
"beslistener",
"beslistener: done terminating default module ... " << endl);
629 strm << BESIndent::LMarg <<
"ServerApp::dump - (" << (
void *)
this <<
")" << endl;
631 strm << BESIndent::LMarg <<
"got IP? " << _gotIP << endl;
632 strm << BESIndent::LMarg <<
"IP: " << _IPVal << endl;
633 strm << BESIndent::LMarg <<
"got port? " << _gotPort << endl;
634 strm << BESIndent::LMarg <<
"port: " << _portVal << endl;
635 strm << BESIndent::LMarg <<
"unix socket: " << _unixSocket << endl;
636 strm << BESIndent::LMarg <<
"is secure? " << _secure << endl;
637 strm << BESIndent::LMarg <<
"pid: " << _mypid << endl;
639 strm << BESIndent::LMarg <<
"tcp socket:" << endl;
642 BESIndent::UnIndent();
645 strm << BESIndent::LMarg <<
"tcp socket: null" << endl;
648 strm << BESIndent::LMarg <<
"unix socket:" << endl;
651 BESIndent::UnIndent();
654 strm << BESIndent::LMarg <<
"unix socket: null" << endl;
657 strm << BESIndent::LMarg <<
"ppt server:" << endl;
660 BESIndent::UnIndent();
663 strm << BESIndent::LMarg <<
"ppt server: null" << endl;
666 BESIndent::UnIndent();
669 int main(
int argc,
char **argv)
673 return app.
main(argc, argv);
676 cerr <<
"Caught unhandled exception: " << endl;
681 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 Register(const std::string &flagName)
register the specified debug flag
virtual std::string get_message()
get the error message for this exception
static void SetUp(const std::string &values)
Sets up debugging for the bes.
virtual int terminate(int sig=0)
clean up after the application
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
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.
static TheBESKeys * TheKeys()
virtual int main(int argC, char **argV)
main routine, the main entry point for any BES applications.
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.
static BESApp * TheApplication(void)
Returns the BESApp application object for this application.
virtual int run()
The body of the application, implementing the primary functionality of the BES application.