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()
270 BESCatalogUtils::delete_all_catalogs();
278 bool needhelp =
false;
285 while ((c = getopt(argc, argv,
"hvsd:c:p:u:i:r:H:")) != -1) {
296 _portVal = atoi(optarg);
304 _unixSocket = optarg;
331 if (!dashc.empty()) {
338 if (dashc.empty() && !dashi.empty()) {
339 if (dashi[dashi.length() - 1] !=
'/') {
342 string conf_file = dashi +
"etc/bes/bes.conf";
358 string port_key =
"BES.ServerPort";
368 exit(SERVER_EXIT_FATAL_CANNOT_START);
371 _portVal = atoi(sPort.c_str());
379 string ip_key =
"BES.ServerIP";
388 exit(SERVER_EXIT_FATAL_CANNOT_START);
397 string socket_key =
"BES.ServerUnixSocket";
398 if (_unixSocket ==
"") {
406 exit(SERVER_EXIT_FATAL_CANNOT_START);
410 if (!_gotPort && _unixSocket ==
"") {
411 string msg =
"Must specify a tcp port or a unix socket or both\n";
412 msg +=
"Please specify on the command line with -p <port>";
413 msg +=
" and/or -u <unix_socket>\n";
414 msg +=
"Or specify in the bes configuration file with " + port_key +
" and/or " + socket_key +
"\n";
421 if (_secure ==
false) {
422 string key =
"BES.ServerSecure";
431 exit(SERVER_EXIT_FATAL_CANNOT_START);
433 if (isSecure ==
"Yes" || isSecure ==
"YES" || isSecure ==
"yes") {
438 BESDEBUG(
"beslistener",
"beslistener: initializing default module ... " << endl);
439 BESDefaultModule::initialize(argc, argv);
440 BESDEBUG(
"beslistener",
"beslistener: done initializing default module" << endl);
442 BESDEBUG(
"beslistener",
"beslistener: initializing default commands ... " << endl);
444 BESDEBUG(
"beslistener",
"beslistener: done initializing default commands" << endl);
447 BESDEBUG(
"beslistener",
"beslistener: initializing loaded modules ... " << endl);
449 BESDEBUG(
"beslistener",
"beslistener: done initializing loaded modules" << endl);
451 BESDEBUG(
"beslistener",
"beslistener: initialized settings:" << *
this);
460 session_id = setsid();
461 BESDEBUG(
"beslistener",
"beslistener: The master beslistener session id (group id): " << session_id << endl);
463 master_listener_pid = getpid();
464 BESDEBUG(
"beslistener",
"beslistener: The master beslistener Process id: " << master_listener_pid << endl);
472 BESDEBUG(
"beslistener",
"beslistener: initializing memory pool ... " << endl);
473 BESMemoryManager::initialize_memory_pool();
474 BESDEBUG(
"beslistener",
"OK" << endl);
483 listener.listen(_ts);
485 BESDEBUG(
"beslistener",
"beslistener: listening on port (" << _portVal <<
")" << endl);
491 int status = BESLISTENER_RUNNING;
492 int res = write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
495 LOG(
"Master listener could not send status to daemon: " << strerror(errno) << endl);
496 ::exit(SERVER_EXIT_FATAL_CANNOT_START);
500 if (!_unixSocket.empty()) {
502 listener.listen(_us);
503 BESDEBUG(
"beslistener",
"beslistener: listening on unix socket (" << _unixSocket <<
")" << endl);
508 _ps =
new PPTServer(&handler, &listener, _secure);
510 register_signal_handlers();
524 if (sigterm | sighup | sigchild | sigpipe) {
527 while ((cpid = wait4(0 , &stat, WNOHANG, 0)) > 0) {
528 _ps->decr_num_children();
530 LOG(
"Master listener caught SISPIPE from child: " << cpid << endl);
534 bes_exit_message(cpid, stat) <<
"; num children: " << _ps->get_num_children() << endl);
539 BESDEBUG(
"ppt2",
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
541 LOG(
"Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
542 ::exit(SERVER_EXIT_RESTART);
546 BESDEBUG(
"ppt2",
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
548 LOG(
"Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
549 ::exit(SERVER_EXIT_NORMAL_SHUTDOWN);
560 _ps->initConnection();
563 _ps->closeConnection();
566 BESDEBUG(
"beslistener",
"beslistener: caught BESError (" << se.
get_message() <<
")" << endl);
569 int status = SERVER_EXIT_FATAL_CANNOT_START;
570 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
571 close(BESLISTENER_PIPE_FD);
575 LOG(
"caught unknown exception initializing sockets" << endl);
576 int status = SERVER_EXIT_FATAL_CANNOT_START;
577 write(BESLISTENER_PIPE_FD, &status,
sizeof(status));
578 close(BESLISTENER_PIPE_FD);
582 close(BESLISTENER_PIPE_FD);
588 pid_t apppid = getpid();
589 if (apppid == _mypid) {
592 _ps->closeConnection();
609 BESDEBUG(
"beslistener",
"beslistener: terminating loaded modules ... " << endl);
611 BESDEBUG(
"beslistener",
"beslistener: done terminating loaded modules" << endl);
613 BESDEBUG(
"beslistener",
"beslistener: terminating default commands ... " << endl);
615 BESDEBUG(
"beslistener",
"beslistener: done terminating default commands ... " << endl);
617 BESDEBUG(
"beslistener",
"beslistener: terminating default module ... " << endl);
618 BESDefaultModule::terminate();
619 BESDEBUG(
"beslistener",
"beslistener: done terminating default module ... " << endl);
634 strm << BESIndent::LMarg <<
"ServerApp::dump - (" << (
void *)
this <<
")" << endl;
636 strm << BESIndent::LMarg <<
"got IP? " << _gotIP << endl;
637 strm << BESIndent::LMarg <<
"IP: " << _IPVal << endl;
638 strm << BESIndent::LMarg <<
"got port? " << _gotPort << endl;
639 strm << BESIndent::LMarg <<
"port: " << _portVal << endl;
640 strm << BESIndent::LMarg <<
"unix socket: " << _unixSocket << endl;
641 strm << BESIndent::LMarg <<
"is secure? " << _secure << endl;
642 strm << BESIndent::LMarg <<
"pid: " << _mypid << endl;
644 strm << BESIndent::LMarg <<
"tcp socket:" << endl;
647 BESIndent::UnIndent();
650 strm << BESIndent::LMarg <<
"tcp socket: null" << endl;
653 strm << BESIndent::LMarg <<
"unix socket:" << endl;
656 BESIndent::UnIndent();
659 strm << BESIndent::LMarg <<
"unix socket: null" << endl;
662 strm << BESIndent::LMarg <<
"ppt server:" << endl;
665 BESIndent::UnIndent();
668 strm << BESIndent::LMarg <<
"ppt server: null" << endl;
671 BESIndent::UnIndent();
674 int main(
int argc,
char **argv)
678 return app.
main(argc, argv);
681 cerr <<
"Caught unhandled exception: " << endl;
686 cerr <<
"Caught unhandled, unknown exception" << endl;