00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Util/log.H"
00039
00040 #include "rutz/compat_snprintf.h"
00041 #include "rutz/demangle.h"
00042 #include "rutz/error_context.h"
00043
00044 #include <cerrno>
00045 #include <cstdarg>
00046 #include <cstdlib>
00047 #include <cstdio>
00048 #include <stdexcept>
00049 #include <sys/types.h>
00050 #include <unistd.h>
00051 #include <cstring>
00052
00053
00054 #define LBS 1024
00055
00056 int LOG_FLAGS = (LFATAL_THROWS
00057 | LFATAL_PRINTS_ABORT
00058 | LFATAL_XTRA_NOISY
00059 | LOG_FULLTRACE);
00060 int MYLOGVERB = LOG_INFO;
00061
00062 lfatal_exception::lfatal_exception() throw() {}
00063
00064 lfatal_exception::~lfatal_exception() throw() {}
00065
00066 const char* MYLOGPREFIX = 0;
00067
00068 namespace
00069 {
00070
00071 class real_lfatal_exception : public lfatal_exception
00072 {
00073 public:
00074 real_lfatal_exception(const std::string& msg)
00075 :
00076 lfatal_exception(),
00077 m_msg(msg)
00078 {}
00079
00080 virtual ~real_lfatal_exception() throw() {}
00081
00082 virtual const char* what() const throw()
00083 {
00084 return m_msg.c_str();
00085 }
00086
00087 std::string m_msg;
00088 };
00089
00090
00091
00092
00093 void sendlog_aux(const char* raw_msg, const int level, const int flags)
00094 {
00095 const char* msg = raw_msg;
00096
00097 std::string full_msg;
00098
00099 if (level == LOG_CRIT)
00100 {
00101
00102
00103
00104 full_msg = raw_msg;
00105 rutz::error_context::current().prepend_to(full_msg);
00106 msg = full_msg.c_str();
00107 }
00108
00109 if (flags & LOG_FULLTRACE)
00110 {
00111
00112
00113
00114 const bool skip_printing =
00115 (level == LOG_CRIT
00116 && (flags & LFATAL_THROWS)
00117 && !(flags & LFATAL_XTRA_NOISY));
00118
00119 if (!skip_printing)
00120 {
00121 if (MYLOGPREFIX != 0)
00122 fprintf(stderr, "[%s] %s\n", MYLOGPREFIX, msg);
00123 else
00124 fprintf(stderr, "%s\n", msg);
00125 fflush(stderr);
00126 }
00127 }
00128 else
00129 syslog(level, "%s", msg);
00130
00131
00132 if (level == LOG_CRIT)
00133 {
00134 if (flags & LFATAL_PRINTS_ABORT)
00135 fprintf(stderr, "-- ABORT.\n");
00136
00137 if (flags & LFATAL_THROWS)
00138 throw real_lfatal_exception(full_msg);
00139
00140 abort();
00141 }
00142 }
00143 }
00144
00145
00146
00147
00148 #ifndef _GNU_SOURCE
00149 int snprintf(char *str, size_t n, const char *format, ...)
00150 { va_list a; va_start(a, format); vsprintf(str, format, a); va_end(a);
00151 return strlen(str); }
00152 int vsnprintf(char *str, size_t n, const char *format, va_list ap)
00153 { vsprintf(str, format, ap); return strlen(str); }
00154 #endif
00155
00156 #ifdef __GNUC__
00157
00158
00159 void sendlog(const int lev, const int line, const char *file,
00160 const char *func, const int idval, const bool useid,
00161 const bool usep, const char *msg, ...)
00162 {
00163 if (lev > MYLOGVERB) return;
00164
00165 va_list args; int len, len2; va_start(args, msg); char logbuf[LBS];
00166
00167
00168 char fil[strlen(file) + 1]; strcpy(fil, file);
00169 for (int i = strlen(fil)-1; i >= 0; i--)
00170 if (fil[i] == '.') { fil[i] = '\0'; break; }
00171
00172 char* fil2 = fil;
00173
00174
00175
00176
00177 if (fil2[0] != '[')
00178 {
00179 fil2 = strrchr(fil, '/');
00180 if (fil2) ++fil2;
00181 else fil2 = fil;
00182 }
00183
00184
00185 len = snprintf(logbuf, LBS, "%s::%s", fil2, func);
00186 if (len == -1 || len >= LBS-1) goto done;
00187
00188 #ifdef DEBUG
00189
00190 len2 = snprintf(&(logbuf[len]), LBS-len, "(%d)", line);
00191 if (len2 == -1 || len2+len >= LBS-1) goto done; else len += len2;
00192 #endif
00193 logbuf[len++] = ':'; if (len >= LBS-1) goto done;
00194
00195
00196 if (useid) {
00197 len2 = snprintf(&(logbuf[len]), LBS-len, "(%d)", idval);
00198 if (len2 == -1 || len2+len >= LBS-1) goto done; else len += len2;
00199 }
00200
00201
00202 if (msg[0] != '(' && msg[0] != '[' && msg[0] != '{')
00203 { logbuf[len++] = ' '; if (len >= LBS-1) goto done; }
00204
00205
00206 len2 = vsnprintf(&(logbuf[len]), LBS-len, msg, args);
00207 if (len2 == -1 || len2+len >= LBS-1) goto done; else len += len2;
00208
00209
00210 if (usep)
00211 snprintf( &(logbuf[len]), LBS-len, " (errno=%d, %s)",
00212 errno, strerror(errno));
00213
00214
00215 done:
00216 va_end(args);
00217
00218 logbuf[LBS - 1] = '\0';
00219
00220 sendlog_aux(logbuf, lev, LOG_FLAGS);
00221 }
00222
00223
00224 void showmemory(const int lev, const int line, const char *file,
00225 const char *func, const int idval, const bool useid,
00226 const bool usep, const char *msg, ...)
00227 {
00228 if (lev > MYLOGVERB) return;
00229
00230
00231 va_list args; va_start(args, msg); char logbuf[LBS + 100];
00232 vsnprintf(logbuf, LBS, msg, args); va_end(args);
00233
00234
00235 int pid = int(getpid());
00236 char xx[100]; snprintf(xx, 100, "/proc/%d/status", pid);
00237 FILE *f = fopen(xx, "r");
00238 if (f == NULL) { LERROR("Cannot open %s -- IGNORED", xx); return; }
00239 while(fgets(xx, 100, f))
00240 if (strncasecmp(xx, "VmSize", 6) == 0)
00241 {
00242 xx[strlen(xx) - 1] = '\0';
00243 xx[7] = ' ';
00244 strcat(logbuf, " [");
00245 strncat(logbuf, xx, 97);
00246 strcat(logbuf, "]");
00247 break;
00248 }
00249 fclose(f);
00250 sendlog(lev, line, file, func, idval, useid, usep, "%s", logbuf);
00251 }
00252
00253 #else
00254
00255
00256 void sendlog(const char *msg, ...)
00257 {
00258 if (MYLOGLEV > MYLOGVERB) return;
00259
00260 va_list args; int len, len2; va_start(args, msg); char logbuf[LBS];
00261
00262
00263 MYLOGFUN[LBS2-1] = '\0'; MYLOGFIL[LBS2-1] = '\0';
00264
00265
00266 for (int i = strlen(MYLOGFIL)-1; i >= 0; i--)
00267 if (MYLOGFIL[i] == '.') { MYLOGFIL[i] = '\0'; break; }
00268
00269
00270 len = snprintf(logbuf, LBS, "%s::%s", MYLOGFIL, MYLOGFUN);
00271 if (len == -1 || len >= LBS-1) goto done;
00272
00273 #ifdef DEBUG
00274
00275 len2 = snprintf(&(logbuf[len]), LBS-len, "(%d)", MYLOGLIN);
00276 if (len2 == -1 || len2+len >= LBS-1) goto done; else len += len2;
00277 #endif
00278 logbuf[len++] = ':'; if (len >= LBS-1) goto done;
00279
00280
00281 if (MYLOG_USEID) {
00282 len2 = snprintf(&(logbuf[len]), LBS-len, "(%d)", MYLOGIDVAL);
00283 if (len2 == -1 || len2+len >= LBS-1) goto done; else len += len2;
00284 }
00285
00286
00287 if (msg[0] != '(' && msg[0] != '[' && msg[0] != '{')
00288 { logbuf[len++] = ' '; if (len >= LBS-1) goto done; }
00289
00290
00291 len2 = vsnprintf(&(logbuf[len]), LBS-len, msg, args);
00292 if (len2 == -1 || len2+len >= LBS-1) goto done; else len += len2;
00293
00294
00295 if (MYLOG_USEP)
00296 snprintf( &(logbuf[len]), LBS-len, " (errno=%d, %s)",
00297 errno, strerror(errno));
00298
00299
00300 done:
00301 va_end(args);
00302
00303 logbuf[LBS - 1] = '\0';
00304
00305 sendlog_aux(logbuf, MYLOGLEV, LOG_FLAGS);
00306 }
00307
00308
00309 char MYLOGFUN[LBS2], MYLOGFIL[LBS2];
00310 int MYLOGLIN, MYLOGLEV, MYLOGIDVAL;
00311 bool MYLOG_USEP, MYLOG_USEID;
00312
00313 #endif
00314
00315 void report_current_exception(const int line, const char* file) throw()
00316 {
00317
00318
00319 try { throw; }
00320 catch (std::exception& e)
00321 {
00322 fprintf(stderr, "%s:%d: exception caught (%s) with what():\n%s\n",
00323 file, line, rutz::demangled_name(typeid(e)), e.what());
00324 fflush(stderr);
00325 }
00326 catch (...)
00327 {
00328 fprintf(stderr, "%s:%d: caught an exception of unknown type\n",
00329 file, line);
00330 fflush(stderr);
00331 }
00332 }
00333
00334
00335
00336
00337
00338