bes  Updated for version 3.17.4
ServerApp.cc
1 // ServerApp.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <unistd.h>
34 #include <signal.h>
35 #include <sys/wait.h> // for wait
36 #include <sys/types.h>
37 
38 #include <iostream>
39 #include <fstream>
40 #include <sstream>
41 #include <cstring>
42 #include <cstdlib>
43 #include <cerrno>
44 
45 #include <libxml/xmlmemory.h>
46 
47 using std::cout;
48 using std::cerr;
49 using std::endl;
50 using std::ios;
51 using std::ostringstream;
52 using std::ofstream;
53 
54 #include "config.h"
55 
56 #include "ServerApp.h"
57 #include "ServerExitConditions.h"
58 #include "TheBESKeys.h"
59 #include "BESLog.h"
60 #include "SocketListener.h"
61 #include "TcpSocket.h"
62 #include "UnixSocket.h"
63 #include "BESServerHandler.h"
64 #include "BESError.h"
65 #include "PPTServer.h"
66 #include "BESMemoryManager.h"
67 #include "BESDebug.h"
68 #include "BESCatalogUtils.h"
69 #include "BESServerUtils.h"
70 
71 #include "BESDefaultModule.h"
72 #include "BESXMLDefaultCommands.h"
73 #include "BESDaemonConstants.h"
74 
75 static int session_id = 0;
76 
77 // These are set to 1 by their respective handlers and then processed in the
78 // signal processing loop.
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;
83 
84 // Set in ServerApp::initialize().
85 // Added jhrg 9/22/15
86 static volatile int master_listener_pid = -1;
87 
88 static string bes_exit_message(int cpid, int stat)
89 {
90  ostringstream oss;
91  oss << "beslistener child pid: " << cpid;
92  if (WIFEXITED(stat)) { // exited via exit()?
93  oss << " exited with status: " << WEXITSTATUS(stat);
94  }
95  else if (WIFSIGNALED(stat)) { // exited via a signal?
96  oss << " exited with signal: " << WTERMSIG(stat);
97 #ifdef WCOREDUMP
98  if (WCOREDUMP(stat)) oss << " and a core dump!";
99 #endif
100  }
101  else {
102  oss << " exited, but I have no clue as to why";
103  }
104 
105  return oss.str();
106 }
107 
108 // These two functions duplicate code in daemon.cc
109 static void block_signals()
110 {
111  sigset_t set;
112  sigemptyset(&set);
113  sigaddset(&set, SIGCHLD);
114  sigaddset(&set, SIGHUP);
115  sigaddset(&set, SIGTERM);
116  sigaddset(&set, SIGPIPE);
117 
118  if (sigprocmask(SIG_BLOCK, &set, 0) < 0) {
119  throw BESInternalError(string("sigprocmask error: ") + strerror(errno) + " while trying to block signals.",
120  __FILE__, __LINE__);
121  }
122 }
123 
124 static void unblock_signals()
125 {
126  sigset_t set;
127  sigemptyset(&set);
128  sigaddset(&set, SIGCHLD);
129  sigaddset(&set, SIGHUP);
130  sigaddset(&set, SIGTERM);
131  sigaddset(&set, SIGPIPE);
132 
133  if (sigprocmask(SIG_UNBLOCK, &set, 0) < 0) {
134  throw BESInternalError(string("sigprocmask error: ") + strerror(errno) + " while trying to unblock signals.",
135  __FILE__, __LINE__);
136  }
137 }
138 
139 // I moved the signal handlers here so that signal processing would be simpler
140 // and no library calls would be made to functions that are not 'asynch safe'.
141 // This was the fix for ticket 2025 and friends (the zombie process problem).
142 // jhrg 3/3/14
143 
144 // This is needed so that the master bes listener will get the exit status of
145 // all of the child bes listeners (preventing them from becoming zombies).
146 static void CatchSigChild(int sig)
147 {
148  if (sig == SIGCHLD) {
149  sigchild = 1;
150  }
151 }
152 
153 // If the HUP signal is sent to the master beslistener, it should exit and
154 // return a value indicating to the besdaemon that it should be restarted.
155 // This also has the side-affect of re-reading the configuration file.
156 static void CatchSigHup(int sig)
157 {
158  if (sig == SIGHUP) {
159  sighup = 1;
160  }
161 }
162 
163 static void CatchSigPipe(int sig)
164 {
165  if (sig == SIGPIPE) {
166  // When a child listener catches SIGPIPE it is because of a
167  // failure on one of its I/O connections - file I/O or, more
168  // likely, network I/O. I have found that C++ ostream objects
169  // seem to 'hide' sigpipe so that a child listener will run
170  // for some time after the client has dropped the
171  // connection. Whether this is from buffering or some other
172  // problem, the situation happens when either the remote
173  // client to exits (e.g., curl) or when Tomcat is stopped
174  // using SIGTERM. So, even though the normal behavior for a
175  // Unix daemon is to look at error codes from write(), etc.,
176  // and exit based on those, this code exits whenever the child
177  // listener catches SIGPIPE. However, if this is the Master
178  // listener, allow the processing loop to handle this signal
179  // and do not exit. jhrg 9/22/15
180  if (getpid() != master_listener_pid) {
181  (*BESLog::TheLog()) << "Child listener caught SIGPIPE (master listener PID: " << master_listener_pid
182  << "). Child listener Exiting." << endl;
183 
184  // cleanup code here; only the Master listener should run the code
185  // in ServerApp::terminate(); do nothing for cleanup for a child
186  // listener. jhrg 9/22/15
187 
188  // Note that exit() is not safe for use in a signal
189  // handler, so we fallback to the default behavior, which
190  // is to exit.
191  signal(sig, SIG_DFL);
192  raise(sig);
193  }
194  else {
195  sigpipe = 1;
196  }
197  }
198 }
199 
200 // This is the default signal sent by 'kill'; when the master beslistener gets
201 // this signal it should stop. besdaemon should not try to start a new
202 // master beslistener.
203 static void CatchSigTerm(int sig)
204 {
205  if (sig == SIGTERM) {
206  sigterm = 1;
207  }
208 }
209 
218 static void register_signal_handlers()
219 {
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);
226  act.sa_flags = 0;
227 #ifdef SA_RESTART
228  BESDEBUG("beslistener", "beslistener: setting restart for sigchld." << endl);
229  act.sa_flags |= SA_RESTART;
230 #endif
231 
232  BESDEBUG("beslistener", "beslistener: Registering signal handlers ... " << endl);
233 
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__,
237  __LINE__);
238 
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__,
242  __LINE__);
243 
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__,
247  __LINE__);
248 
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__,
252  __LINE__);
253 
254  BESDEBUG("beslistener", "beslistener: OK" << endl);
255 }
256 
257 ServerApp::ServerApp() :
258  BESModuleApp(), _portVal(0), _gotPort(false), _IPVal(""), _gotIP(false), _unixSocket(""), _secure(false), _mypid(0), _ts(0), _us(0), _ps(0)
259 {
260  _mypid = getpid();
261 }
262 
263 ServerApp::~ServerApp()
264 {
265  delete TheBESKeys::TheKeys();
266 
267  BESCatalogUtils::delete_all_catalogs();
268 }
269 
270 int ServerApp::initialize(int argc, char **argv)
271 {
272  int c = 0;
273  bool needhelp = false;
274  string dashi;
275  string dashc;
276  string dashd = "";
277 
278  // If you change the getopt statement below, be sure to make the
279  // corresponding change in daemon.cc and besctl.in
280  while ((c = getopt(argc, argv, "hvsd:c:p:u:i:r:H:")) != -1) {
281  switch (c) {
282  case 'i':
283  dashi = optarg;
284  break;
285  case 'c':
286  dashc = optarg;
287  break;
288  case 'r':
289  break; // we can ignore the /var/run directory option here
290  case 'p':
291  _portVal = atoi(optarg);
292  _gotPort = true;
293  break;
294  case 'H':
295  _IPVal = optarg;
296  _gotIP = true;
297  break;
298  case 'u':
299  _unixSocket = optarg;
300  break;
301  case 'd':
302  dashd = optarg;
303  // BESDebug::SetUp(optarg);
304  break;
305  case 'v':
306  BESServerUtils::show_version(BESApp::TheApplication()->appName());
307  break;
308  case 's':
309  _secure = true;
310  break;
311  case 'h':
312  case '?':
313  default:
314  needhelp = true;
315  break;
316  }
317  }
318 
319  // before we can do any processing, log any messages, initialize any
320  // modules, do anything, we need to determine where the BES
321  // configuration file lives. From here we get the name of the log
322  // file, group and user id, and information that the modules will
323  // need to run properly.
324 
325  // If the -c option was passed, set the config file name in TheBESKeys
326  if (!dashc.empty()) {
327  TheBESKeys::ConfigFile = dashc;
328  }
329 
330  // If the -c option was not passed, but the -i option
331  // was passed, then use the -i option to construct
332  // the path to the config file
333  if (dashc.empty() && !dashi.empty()) {
334  if (dashi[dashi.length() - 1] != '/') {
335  dashi += '/';
336  }
337  string conf_file = dashi + "etc/bes/bes.conf";
338  TheBESKeys::ConfigFile = conf_file;
339  }
340 
341  if (!dashd.empty()) BESDebug::SetUp(dashd);
342 
343  // register the two debug context for the server and ppt. The
344  // Default Module will register the bes context.
345  BESDebug::Register("server");
346  BESDebug::Register("ppt");
347 
348  // Because we are now running as the user specified in the
349  // configuration file, we won't be able to listen on system ports.
350  // If this is a problem, we may need to move this code above setting
351  // the user and group ids.
352  bool found = false;
353  string port_key = "BES.ServerPort";
354  if (!_gotPort) {
355  string sPort;
356  try {
357  TheBESKeys::TheKeys()->get_value(port_key, sPort, found);
358  }
359  catch (BESError &e) {
360  string err = string("FAILED: ") + e.get_message();
361  cerr << err << endl;
362  (*BESLog::TheLog()) << err << endl;
363  exit(SERVER_EXIT_FATAL_CANNOT_START);
364  }
365  if (found) {
366  _portVal = atoi(sPort.c_str());
367  if (_portVal != 0) {
368  _gotPort = true;
369  }
370  }
371  }
372 
373  found = false;
374  string ip_key = "BES.ServerIP";
375  if (!_gotIP) {
376  try {
377  TheBESKeys::TheKeys()->get_value(ip_key, _IPVal, found);
378  }
379  catch (BESError &e) {
380  string err = string("FAILED: ") + e.get_message();
381  cerr << err << endl;
382  (*BESLog::TheLog()) << err << endl;
383  exit(SERVER_EXIT_FATAL_CANNOT_START);
384  }
385 
386  if (found) {
387  _gotIP = true;
388  }
389  }
390 
391  found = false;
392  string socket_key = "BES.ServerUnixSocket";
393  if (_unixSocket == "") {
394  try {
395  TheBESKeys::TheKeys()->get_value(socket_key, _unixSocket, found);
396  }
397  catch (BESError &e) {
398  string err = string("FAILED: ") + e.get_message();
399  cerr << err << endl;
400  (*BESLog::TheLog()) << err << endl;
401  exit(SERVER_EXIT_FATAL_CANNOT_START);
402  }
403  }
404 
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";
410  cout << endl << msg;
411  (*BESLog::TheLog()) << msg << endl;
412  BESServerUtils::show_usage(BESApp::TheApplication()->appName());
413  }
414 
415  found = false;
416  if (_secure == false) {
417  string key = "BES.ServerSecure";
418  string isSecure;
419  try {
420  TheBESKeys::TheKeys()->get_value(key, isSecure, found);
421  }
422  catch (BESError &e) {
423  string err = string("FAILED: ") + e.get_message();
424  cerr << err << endl;
425  (*BESLog::TheLog()) << err << endl;
426  exit(SERVER_EXIT_FATAL_CANNOT_START);
427  }
428  if (isSecure == "Yes" || isSecure == "YES" || isSecure == "yes") {
429  _secure = true;
430  }
431  }
432 
433  BESDEBUG("beslistener", "beslistener: initializing default module ... " << endl);
434  BESDefaultModule::initialize(argc, argv);
435  BESDEBUG("beslistener", "beslistener: done initializing default module" << endl);
436 
437  BESDEBUG("beslistener", "beslistener: initializing default commands ... " << endl);
439  BESDEBUG("beslistener", "beslistener: done initializing default commands" << endl);
440 
441  // This will load and initialize all of the modules
442  BESDEBUG("beslistener", "beslistener: initializing loaded modules ... " << endl);
443  int ret = BESModuleApp::initialize(argc, argv);
444  BESDEBUG("beslistener", "beslistener: done initializing loaded modules" << endl);
445 
446  BESDEBUG("beslistener", "beslistener: initialized settings:" << *this);
447 
448  if (needhelp) {
449  BESServerUtils::show_usage(BESApp::TheApplication()->appName());
450  }
451 
452  // This sets the process group to be ID of this process. All children
453  // will get this GID. Then use killpg() to send a signal to this process
454  // and all of the children.
455  session_id = setsid();
456  BESDEBUG("beslistener", "beslistener: The master beslistener session id (group id): " << session_id << endl);
457 
458  master_listener_pid = getpid();
459  BESDEBUG("beslistener", "beslistener: The master beslistener Process id: " << master_listener_pid << endl);
460 
461  return ret;
462 }
463 
465 {
466  try {
467  BESDEBUG("beslistener", "beslistener: initializing memory pool ... " << endl);
468  BESMemoryManager::initialize_memory_pool();
469  BESDEBUG("beslistener", "OK" << endl);
470 
471  SocketListener listener;
472  if (_portVal) {
473  if (!_IPVal.empty())
474  _ts = new TcpSocket(_IPVal, _portVal);
475  else
476  _ts = new TcpSocket(_portVal);
477 
478  listener.listen(_ts);
479 
480  BESDEBUG("beslistener", "beslistener: listening on port (" << _portVal << ")" << endl);
481 
482  // Write to stdout works because the besdaemon is listening on the
483  // other end of a pipe where the pipe fd[1] has been dup2'd to
484  // stdout. See daemon.cc:start_master_beslistener.
485  // NB BESLISTENER_PIPE_FD is 1 (stdout)
486  int status = BESLISTENER_RUNNING;
487  int res = write(BESLISTENER_PIPE_FD, &status, sizeof(status));
488 
489  if (res == -1) {
490  (*BESLog::TheLog()) << "Master listener could not send status to daemon: " << strerror(errno) << endl;
491  ::exit(SERVER_EXIT_FATAL_CANNOT_START);
492  }
493  }
494 
495  if (!_unixSocket.empty()) {
496  _us = new UnixSocket(_unixSocket);
497  listener.listen(_us);
498  BESDEBUG("beslistener", "beslistener: listening on unix socket (" << _unixSocket << ")" << endl);
499  }
500 
501  BESServerHandler handler;
502 
503  _ps = new PPTServer(&handler, &listener, _secure);
504 
505  register_signal_handlers();
506 
507  // Loop forever, processing signals and running the code in PPTServer::initConnection().
508  // NB: The code in initConnection() used to loop forever, but I moved that out to here
509  // so the signal handlers could be in this class. The PPTServer::initConnection() method
510  // is also used by daemon.cc but this class (ServerApp; the beslistener) and the besdaemon
511  // need to do different things for the signals like HUP and TERM, so they cannot share
512  // the signal processing code. One fix for the problem described in ticket 2025 was to
513  // move the signal handlers into PPTServer. Changing how the 'forever' loops are organized
514  // and keeping the signal processing code here (and in daemon.cc) is another solution that
515  // preserves the correct behavior of the besdaemon, too. jhrg 3/5/14
516  while (true) {
517  block_signals();
518 
519  if (sigterm | sighup | sigchild | sigpipe) {
520  int stat;
521  pid_t cpid;
522  while ((cpid = wait4(0 /*any child in the process group*/, &stat, WNOHANG, 0/*no rusage*/)) > 0) {
523  _ps->decr_num_children();
524  if (sigpipe) {
525  (*BESLog::TheLog()) << "Master listener caught SISPIPE from child: " << cpid << endl;
526  }
527 
528  BESDEBUG("ppt2",
529  bes_exit_message(cpid, stat) << "; num children: " << _ps->get_num_children() << endl);
530  }
531  }
532 
533  if (sighup) {
534  BESDEBUG("ppt2", "Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
535 
536  (*BESLog::TheLog()) << "Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl;
537  ::exit(SERVER_EXIT_RESTART);
538  }
539 
540  if (sigterm) {
541  BESDEBUG("ppt2", "Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
542 
543  (*BESLog::TheLog()) << "Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl;
544  ::exit(SERVER_EXIT_NORMAL_SHUTDOWN);
545  }
546 
547  sigchild = 0; // Only reset this signal, all others cause an exit/restart
548  unblock_signals();
549 
550  // This is where the 'child listener' is started. This method will call
551  // BESServerHandler::handle(...) that will, in turn, fork. The child process
552  // becomes the 'child listener' that actually processes a request.
553  _ps->initConnection();
554  }
555 
556  _ps->closeConnection();
557  }
558  catch (BESError &se) {
559  BESDEBUG("beslistener", "beslistener: caught BESError (" << se.get_message() << ")" << endl);
560 
561  (*BESLog::TheLog()) << 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);
565  return 1;
566  }
567  catch (...) {
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);
572  return 1;
573  }
574 
575  close(BESLISTENER_PIPE_FD);
576  return 0;
577 }
578 
580 {
581  pid_t apppid = getpid();
582  if (apppid == _mypid) {
583  // These are all safe to call in a signalhandler
584  if (_ps) {
585  _ps->closeConnection();
586  delete _ps;
587  }
588  if (_ts) {
589  _ts->close();
590  delete _ts;
591  }
592  if (_us) {
593  _us->close();
594  delete _us;
595  }
596 
597  // Do this in the reverse order that it was initialized. So
598  // terminate the loaded modules first, then the default
599  // commands, then the default module.
600 
601  // These are not safe to call in a signal handler
602  BESDEBUG("beslistener", "beslistener: terminating loaded modules ... " << endl);
604  BESDEBUG("beslistener", "beslistener: done terminating loaded modules" << endl);
605 
606  BESDEBUG("beslistener", "beslistener: terminating default commands ... " << endl);
608  BESDEBUG("beslistener", "beslistener: done terminating default commands ... " << endl);
609 
610  BESDEBUG("beslistener", "beslistener: terminating default module ... " << endl);
611  BESDefaultModule::terminate();
612  BESDEBUG("beslistener", "beslistener: done terminating default module ... " << endl);
613 
614  xmlCleanupParser();
615  }
616  return sig;
617 }
618 
625 void ServerApp::dump(ostream &strm) const
626 {
627  strm << BESIndent::LMarg << "ServerApp::dump - (" << (void *) this << ")" << endl;
628  BESIndent::Indent();
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;
636  if (_ts) {
637  strm << BESIndent::LMarg << "tcp socket:" << endl;
638  BESIndent::Indent();
639  _ts->dump(strm);
640  BESIndent::UnIndent();
641  }
642  else {
643  strm << BESIndent::LMarg << "tcp socket: null" << endl;
644  }
645  if (_us) {
646  strm << BESIndent::LMarg << "unix socket:" << endl;
647  BESIndent::Indent();
648  _us->dump(strm);
649  BESIndent::UnIndent();
650  }
651  else {
652  strm << BESIndent::LMarg << "unix socket: null" << endl;
653  }
654  if (_ps) {
655  strm << BESIndent::LMarg << "ppt server:" << endl;
656  BESIndent::Indent();
657  _ps->dump(strm);
658  BESIndent::UnIndent();
659  }
660  else {
661  strm << BESIndent::LMarg << "ppt server: null" << endl;
662  }
663  BESModuleApp::dump(strm);
664  BESIndent::UnIndent();
665 }
666 
667 int main(int argc, char **argv)
668 {
669  try {
670  ServerApp app;
671  return app.main(argc, argv);
672  }
673  catch (BESError &e) {
674  cerr << "Caught unhandled exception: " << endl;
675  cerr << e.get_message() << endl;
676  return 1;
677  }
678  catch (...) {
679  cerr << "Caught unhandled, unknown exception" << endl;
680  return 1;
681  }
682  return 0;
683 }
684 
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.
Definition: BESDebug.cc:68
virtual int main(int argC, char **argV)
main method of the BES application
Definition: BESBaseApp.cc:74
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:97
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.
virtual void initConnection()
Definition: PPTServer.cc:134
Abstract exception class for the BES with basic string message.
Definition: BESError.h:56
virtual void dump(ostream &strm) const
dumps information about this object
Definition: PPTServer.cc:272
virtual void dump(ostream &strm) const
dumps information about this object
Definition: ServerApp.cc:625
virtual int terminate(int sig=0)
clean up after the application
Definition: ServerApp.cc:579
virtual void dump(ostream &strm) const
dumps information about this object
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
Definition: ServerApp.cc:270
Base application object for all BES applications.
Definition: BESModuleApp.h:59
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
Definition: BESModuleApp.cc:70
string appName(void) const
Returns the name of the application.
Definition: BESApp.h:132
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:483
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:43
static void Register(const string &flagName)
register the specified debug flag
Definition: BESDebug.h:145
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: TcpSocket.cc:593
static BESApp * TheApplication(void)
Returns the BESApp application object for this application.
Definition: BESApp.h:138
virtual int run()
the applications functionality is implemented in the run method
Definition: ServerApp.cc:464
virtual void dump(ostream &strm) const
dumps information about this object
Definition: UnixSocket.cc:246
static string ConfigFile
Definition: TheBESKeys.h:53