36 #include <sys/types.h>
45 #include <libxml/xmlmemory.h>
51 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 (*BESLog::TheLog()) <<
"Child listener (PID: " << getpid() <<
") caught SIGPIPE (master listener PID: "
184 << master_listener_pid <<
"). Child listener Exiting." << endl;
193 signal(sig, SIG_DFL);
197 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";
370 exit(SERVER_EXIT_FATAL_CANNOT_START);
373 _portVal = atoi(sPort.c_str());
381 string ip_key =
"BES.ServerIP";
390 exit(SERVER_EXIT_FATAL_CANNOT_START);
399 string socket_key =
"BES.ServerUnixSocket";
400 if (_unixSocket ==
"") {
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";
423 if (_secure ==
false) {
424 string key =
"BES.ServerSecure";
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 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 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 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 LOG(
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
551 ::exit(SERVER_EXIT_NORMAL_SHUTDOWN);
562 _ps->initConnection();
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 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;