TError.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TError.cxx 37217 2010-12-03 11:24:41Z rdm $
00002 // Author: Fons Rademakers   29/07/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // Error handling routines.                                             //
00015 //                                                                      //
00016 // This file defines a number of global error handling routines:        //
00017 // Warning(), Error(), SysError() and Fatal(). They all take a          //
00018 // location string (where the error happened) and a printf style format //
00019 // string plus vararg's. In the end these functions call an             //
00020 // errorhandler function. By default DefaultErrorHandler() is used.     //
00021 //                                                                      //
00022 //////////////////////////////////////////////////////////////////////////
00023 
00024 #ifdef WIN32
00025 #include <windows.h>
00026 #endif
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include "snprintf.h"
00031 #include "Varargs.h"
00032 #include "Riostream.h"
00033 #include "TError.h"
00034 #include "TSystem.h"
00035 #include "TString.h"
00036 #include "TEnv.h"
00037 #include "TVirtualMutex.h"
00038 
00039 // Mutex for error and error format protection
00040 // (exported to be used for similar cases in other classes)
00041 
00042 TVirtualMutex *gErrorMutex = 0;
00043 
00044 Int_t  gErrorIgnoreLevel     = kUnset;
00045 Int_t  gErrorAbortLevel      = kSysError+1;
00046 Bool_t gPrintViaErrorHandler = kFALSE;
00047 
00048 const char *kAssertMsg = "%s violated at line %d of `%s'";
00049 const char *kCheckMsg  = "%s not true at line %d of `%s'";
00050 
00051 // Integrate with crash reporter.
00052 #ifdef __APPLE__
00053 extern "C" const char *__crashreporter_info__;
00054 const char *__crashreporter_info__ = 0;
00055 #endif
00056 
00057 static ErrorHandlerFunc_t gErrorHandler = DefaultErrorHandler;
00058 
00059 
00060 //______________________________________________________________________________
00061 static void DebugPrint(const char *fmt, ...)
00062 {
00063    // Print debugging message to stderr and, on Windows, to the system debugger.
00064 
00065    static Int_t buf_size = 2048;
00066    static char *buf = 0;
00067 
00068    R__LOCKGUARD2(gErrorMutex);
00069 
00070    va_list ap;
00071    va_start(ap, fmt);
00072 
00073 again:
00074    if (!buf)
00075       buf = new char[buf_size];
00076 
00077    Int_t n = vsnprintf(buf, buf_size, fmt, ap);
00078    // old vsnprintf's return -1 if string is truncated new ones return
00079    // total number of characters that would have been written
00080    if (n == -1 || n >= buf_size) {
00081       if (n == -1)
00082          buf_size *= 2;
00083       else
00084          buf_size = n+1;
00085       delete [] buf;
00086       buf = 0;
00087       va_end(ap);
00088       va_start(ap, fmt);
00089       goto again;
00090    }
00091    va_end(ap);
00092 
00093    fprintf(stderr, "%s", buf);
00094 
00095 #ifdef WIN32
00096    ::OutputDebugString(buf);
00097 #endif
00098 }
00099 
00100 //______________________________________________________________________________
00101 ErrorHandlerFunc_t SetErrorHandler(ErrorHandlerFunc_t newhandler)
00102 {
00103    // Set an errorhandler function. Returns the old handler.
00104 
00105    ErrorHandlerFunc_t oldhandler = gErrorHandler;
00106    gErrorHandler = newhandler;
00107    return oldhandler;
00108 }
00109 
00110 //______________________________________________________________________________
00111 ErrorHandlerFunc_t GetErrorHandler()
00112 {
00113    // Returns the current error handler function.
00114 
00115    return gErrorHandler;
00116 }
00117 
00118 //______________________________________________________________________________
00119 void DefaultErrorHandler(Int_t level, Bool_t abort_bool, const char *location, const char *msg)
00120 {
00121    // The default error handler function. It prints the message on stderr and
00122    // if abort is set it aborts the application.
00123 
00124    if (gErrorIgnoreLevel == kUnset) {
00125       R__LOCKGUARD2(gErrorMutex);
00126 
00127       gErrorIgnoreLevel = 0;
00128       if (gEnv) {
00129          TString slevel = gEnv->GetValue("Root.ErrorIgnoreLevel", "Print");
00130          if (!slevel.CompareTo("Print", TString::kIgnoreCase))
00131             gErrorIgnoreLevel = kPrint;
00132          else if (!slevel.CompareTo("Info", TString::kIgnoreCase))
00133             gErrorIgnoreLevel = kInfo;
00134          else if (!slevel.CompareTo("Warning", TString::kIgnoreCase))
00135             gErrorIgnoreLevel = kWarning;
00136          else if (!slevel.CompareTo("Error", TString::kIgnoreCase))
00137             gErrorIgnoreLevel = kError;
00138          else if (!slevel.CompareTo("Break", TString::kIgnoreCase))
00139             gErrorIgnoreLevel = kBreak;
00140          else if (!slevel.CompareTo("SysError", TString::kIgnoreCase))
00141             gErrorIgnoreLevel = kSysError;
00142          else if (!slevel.CompareTo("Fatal", TString::kIgnoreCase))
00143             gErrorIgnoreLevel = kFatal;
00144       }
00145    }
00146 
00147    if (level < gErrorIgnoreLevel)
00148       return;
00149 
00150    const char *type = 0;
00151 
00152    if (level >= kInfo)
00153       type = "Info";
00154    if (level >= kWarning)
00155       type = "Warning";
00156    if (level >= kError)
00157       type = "Error";
00158    if (level >= kBreak)
00159       type = "\n *** Break ***";
00160    if (level >= kSysError)
00161       type = "SysError";
00162    if (level >= kFatal)
00163       type = "Fatal";
00164 
00165    TString smsg;
00166    if (level >= kPrint && level < kInfo)
00167       smsg.Form("%s", msg);
00168    else if (level >= kBreak && level < kSysError)
00169       smsg.Form("%s %s", type, msg);
00170    else if (!location || strlen(location) == 0)
00171       smsg.Form("%s: %s", type, msg);
00172    else
00173       smsg.Form("%s in <%s>: %s", type, location, msg);
00174 
00175    DebugPrint("%s\n", smsg.Data());
00176 
00177 #ifdef __APPLE__
00178    if (__crashreporter_info__)
00179       delete [] __crashreporter_info__;
00180    __crashreporter_info__ = StrDup(smsg);
00181 #endif
00182 
00183    fflush(stderr);
00184    if (abort_bool) {
00185       DebugPrint("aborting\n");
00186       fflush(stderr);
00187       if (gSystem) {
00188          gSystem->StackTrace();
00189          gSystem->Abort();
00190       } else
00191          abort();
00192    }
00193 }
00194 
00195 //______________________________________________________________________________
00196 void ErrorHandler(Int_t level, const char *location, const char *fmt, va_list ap)
00197 {
00198    // General error handler function. It calls the user set error handler.
00199 
00200    R__LOCKGUARD2(gErrorMutex);
00201 
00202    static Int_t buf_size = 2048;
00203    static char *buf = 0;
00204 
00205    int vc = 0;
00206    va_list sap;
00207    R__VA_COPY(sap, ap);
00208 
00209 again:
00210    if (!buf)
00211       buf = new char[buf_size];
00212 
00213    if (!fmt)
00214       fmt = "no error message provided";
00215 
00216    Int_t n = vsnprintf(buf, buf_size, fmt, ap);
00217    // old vsnprintf's return -1 if string is truncated new ones return
00218    // total number of characters that would have been written
00219    if (n == -1 || n >= buf_size) {
00220       if (n == -1)
00221          buf_size *= 2;
00222       else
00223          buf_size = n+1;
00224       delete [] buf;
00225       buf = 0;
00226       va_end(ap);
00227       R__VA_COPY(ap, sap);
00228       vc = 1;
00229       goto again;
00230    }
00231    va_end(sap);
00232    if (vc)
00233       va_end(ap);
00234 
00235    char *bp;
00236    if (level >= kSysError && level < kFatal)
00237       bp = Form("%s (%s)", buf, gSystem->GetError());
00238    else
00239       bp = buf;
00240 
00241    if (level != kFatal)
00242       gErrorHandler(level, level >= gErrorAbortLevel, location, bp);
00243    else
00244       gErrorHandler(level, kTRUE, location, bp);
00245 }
00246 
00247 //______________________________________________________________________________
00248 void AbstractMethod(const char *method)
00249 {
00250    // This function can be used in abstract base classes in case one does
00251    // not want to make the class a "real" (in C++ sense) ABC. If this
00252    // function is called it will warn the user that the function should
00253    // have been overridden.
00254 
00255    Warning(method, "this method must be overridden!");
00256 }
00257 
00258 //______________________________________________________________________________
00259 void MayNotUse(const char *method)
00260 {
00261    // This function can be used in classes that should override a certain
00262    // function, but in the inherited class the function makes no sense.
00263 
00264    Warning(method, "may not use this method");
00265 }
00266 
00267 //______________________________________________________________________________
00268 void Error(const char *location, const char *va_(fmt), ...)
00269 {
00270    // Use this function in case an error occured.
00271 
00272    va_list ap;
00273    va_start(ap,va_(fmt));
00274    ErrorHandler(kError, location, va_(fmt), ap);
00275    va_end(ap);
00276 }
00277 
00278 //______________________________________________________________________________
00279 void SysError(const char *location, const char *va_(fmt), ...)
00280 {
00281    // Use this function in case a system (OS or GUI) related error occured.
00282 
00283    va_list ap;
00284    va_start(ap, va_(fmt));
00285    ErrorHandler(kSysError, location, va_(fmt), ap);
00286    va_end(ap);
00287 }
00288 
00289 //______________________________________________________________________________
00290 void Break(const char *location, const char *va_(fmt), ...)
00291 {
00292    // Use this function in case an error occured.
00293 
00294    va_list ap;
00295    va_start(ap,va_(fmt));
00296    ErrorHandler(kBreak, location, va_(fmt), ap);
00297    va_end(ap);
00298 }
00299 
00300 //______________________________________________________________________________
00301 void Info(const char *location, const char *va_(fmt), ...)
00302 {
00303    // Use this function for informational messages.
00304 
00305    va_list ap;
00306    va_start(ap,va_(fmt));
00307    ErrorHandler(kInfo, location, va_(fmt), ap);
00308    va_end(ap);
00309 }
00310 
00311 //______________________________________________________________________________
00312 void Warning(const char *location, const char *va_(fmt), ...)
00313 {
00314    // Use this function in warning situations.
00315 
00316    va_list ap;
00317    va_start(ap,va_(fmt));
00318    ErrorHandler(kWarning, location, va_(fmt), ap);
00319    va_end(ap);
00320 }
00321 
00322 //______________________________________________________________________________
00323 void Fatal(const char *location, const char *va_(fmt), ...)
00324 {
00325    // Use this function in case of a fatal error. It will abort the program.
00326 
00327    va_list ap;
00328    va_start(ap,va_(fmt));
00329    ErrorHandler(kFatal, location, va_(fmt), ap);
00330    va_end(ap);
00331 }

Generated on Tue Jul 5 14:11:20 2011 for ROOT_528-00b_version by  doxygen 1.5.1