main.cpp

Go to the documentation of this file.
00001 /**
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** @file main.cpp Main application entry point. */
00020 
00021 #include <hn/hnprec.h>
00022 #include <hn/hydranode.h>
00023 #include <hn/log.h>
00024 
00025 #ifdef HAVE_EXECINFO_H
00026         #include <execinfo.h>
00027 #endif
00028 
00029 /**
00030  * Prints call trace to standard error device
00031  */
00032 void do_backtrace();
00033 
00034 /**
00035  * Handles termination event from system
00036  */
00037 void on_terminate();
00038 
00039 /**
00040  * Handles fatal exceptions event from system
00041  */
00042 void on_fatal_exception();
00043 
00044 /**
00045  * Signal handler (on POSIX systems only). Attempts to perform a clean shutdown
00046  * when SIGQUIT or SIGTERM is received.
00047  */
00048 void onSignal(int signum);
00049 
00050 //! Signal handler for fatal crash signals
00051 void onCrash(int signum);
00052 
00053 #if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION)
00054 #include <signal.h>
00055 void initSignalHandlers() {
00056         struct sigaction sa;
00057         memset(&sa, 0, sizeof(struct sigaction));
00058         sa.sa_handler = &onSignal;
00059         sigaction(SIGQUIT, &sa, 0);
00060         sigaction(SIGTERM, &sa, 0);
00061         sigaction(SIGINT,  &sa, 0);
00062 #ifdef SIGXFSZ
00063         sigaction(SIGXFSZ, &sa, 0);
00064 #endif
00065         signal(SIGPIPE, SIG_IGN); // Ignore SIGPIPE
00066 }
00067 
00068 void onSignal(int signum) {
00069         if (signum != SIGQUIT && signum != SIGTERM && signum != SIGINT) {
00070                 return;
00071         }
00072 #ifdef SIGXFSZ
00073         if (signum == SIGXFSZ) {
00074                 logWarning(
00075                         "Program received signal SIGXFSZ "
00076                         "(File size limit exceeded)"
00077                 );
00078                 return;
00079         }
00080 #endif
00081         HydraNode::instance().exit();
00082 }
00083 #else // Not implemented
00084 void initSignalHandlers() {}
00085 #endif
00086 
00087 /**
00088  * Automatic trace back printing on fatal errors.
00089  */
00090 void do_backtrace() {
00091 #ifdef HAVE_EXECINFO_H
00092         void *bt_array[100];
00093         char **bt_strings;
00094         int num_entries;
00095         if ((num_entries = backtrace(bt_array, 100)) < 0) {
00096                 std::cerr << "* Could not generate backtrace.\n";
00097                 return;
00098         }
00099         if ((bt_strings = backtrace_symbols(bt_array, num_entries)) == NULL) {
00100                 std::cerr << "* Could not get symbol names for backtrace.\n";
00101                 return;
00102         }
00103         for (int i = 0; i < num_entries; ++i) {
00104                 std::cerr << " [" << i << "] " << bt_strings[i] << std::endl;
00105         }
00106         free(bt_strings);
00107 #endif
00108 }
00109 
00110 void on_terminate() {
00111         std::cerr << "\n\nOoops..." << std::endl;
00112         std::cerr << "HydraNode has performed an illegal operation ";
00113         std::cerr << "and has been shut down." << std::endl;
00114 #ifdef HAVE_EXECINFO_H
00115         std::cerr << "Call trace:" << std::endl;
00116         do_backtrace();
00117 #endif
00118         std::cerr << "\nAttempting to retrieve last log messages:\n";
00119         Log::printLast(10);
00120 }
00121 
00122 void on_fatal_exception() {
00123         std::cerr << "\n\nOoops..." << std::endl;
00124         std::cerr << "A fatal exception happened within HydraNode.";
00125 #ifdef HAVE_EXECINFO_H
00126         std::cerr << "\n\nCall trace:" << std::endl;
00127         do_backtrace();
00128 #endif
00129         std::cerr << "\nAttempting to retrieve last log messages:\n";
00130         Log::printLast(10);
00131 }
00132 
00133 // Application entry point
00134 int main(int argc, char *argv[]) {
00135         std::set_terminate(&on_terminate);
00136         std::set_unexpected(&on_fatal_exception);
00137         initSignalHandlers();
00138         return HydraNode::instance().run(argc, argv);
00139 }