Changeset 165 for Evidence/Evidence.cc


Ignore:
Timestamp:
02/09/10 06:49:45 (15 years ago)
Author:
ogrimm
Message:
Improved C++ unhandled exception handling
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Evidence.cc

    r164 r165  
    1515  - The static method ToString() converts the contents of a
    1616    DIMInfo service into text
    17        
     17  - A terminate-handler is installed for catching unhandled C++ exceptions.
     18 
    1819  All memory allocated by the non-static methods will be freed by the
    1920  class destructor.
    2021 
    21   Oliver Grimm, December 2009
     22  Oliver Grimm, February 2009
    2223 
    2324\********************************************************************/
     
    5152 
    5253  // Start server
    53   static char Init[] = "Server started (" EVIDENCE_REVISION "  Compiled "__DATE__ __TIME__ ")";
    54   Status = new DimService((string(Name) + "/Status").c_str(), (char *) "C", Init, sizeof(Init));
     54  string Rev(EVIDENCE_REVISION);
     55  Rev = Rev.substr(1, Rev.size()-3);
     56  if (asprintf(&InitMsg, "Server started (%s, compiled %s)", Rev.c_str(),__TIMESTAMP__) == -1) InitMsg = NULL;
     57 
     58  Status = new DimService((string(Name) + "/Status").c_str(), (char *) "C", InitMsg, strlen(InitMsg)+1);
    5559
    5660  start(Name);
     
    6165EvidenceServer::~EvidenceServer() {
    6266
     67  free(InitMsg);
    6368  State(INFO, "Server stopped");
    6469 
     
    182187}
    183188
    184 // C++ exception handler
     189// C++ exception handler (derived from gcc __verbose_terminate_handler())
    185190void EvidenceServer::Terminate() {
    186191
    187   string Msg = string(ThisServer->Status->getName()) + ": Caught unhandled exception";
    188 
    189   printf("%s\n", Msg.c_str());
    190   DimClient::sendCommand("DColl/Log", Msg.c_str());
    191  
    192   abort();
     192  static char Msg[STATUS_SIZE];
     193  static bool Terminating = false;
     194
     195  if (Terminating) {
     196        snprintf(Msg, sizeof(Msg), "%s: Terminate() called recursively, calling abort()", ThisServer->Status->getName());
     197        printf("%s\n", Msg);
     198        DimClient::sendCommandNB("DColl/Log", Msg);
     199        abort();
     200  }
     201  else {
     202        Terminating = true;
     203
     204        // Make sure there was an exception; terminate is also called for an
     205        // attempt to rethrow when there is no suitable exception.
     206        type_info *Type = abi::__cxa_current_exception_type();
     207        if (Type != NULL) {
     208          int Status = -1;
     209          char *Demangled = NULL;
     210
     211          Demangled = abi::__cxa_demangle(Type->name(), 0, 0, &Status);
     212          snprintf(Msg, sizeof(Msg), "%s: Terminate() called after throwing an instance of '%s'", ThisServer->Status->getName(), Status==0 ? Demangled : Type->name());
     213          free(Demangled);
     214
     215          // If exception derived from std::exception, more information.
     216          try { __throw_exception_again; }
     217          catch (exception &E) {
     218                snprintf(Msg+strlen(Msg), sizeof(Msg)-strlen(Msg), " (what(): %s)", E.what());   
     219          }
     220          catch (...) { }
     221        }
     222        else snprintf(Msg, sizeof(Msg), "%s: Terminate() called without an active exception", ThisServer->Status->getName());
     223  }
     224
     225  ThisServer->State(FATAL, Msg);
    193226}
    194227
Note: See TracChangeset for help on using the changeset viewer.