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