comparison Core/Logging.cpp @ 2134:ddc75c6c712d

Avoid hard crash if not enough memory
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 09 Nov 2016 12:04:09 +0100
parents bcc575732aef
children aa4b8895cd23
comparison
equal deleted inserted replaced
2133:15ae532af70e 2134:ddc75c6c712d
316 { 316 {
317 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); 317 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n");
318 return; 318 return;
319 } 319 }
320 320
321 LogLevel l = StringToLogLevel(level); 321 try
322 322 {
323 if ((l == LogLevel_Info && !loggingContext_->infoEnabled_) || 323 LogLevel l = StringToLogLevel(level);
324 (l == LogLevel_Trace && !loggingContext_->traceEnabled_)) 324
325 { 325 if ((l == LogLevel_Info && !loggingContext_->infoEnabled_) ||
326 // This logging level is disabled, directly exit and unlock 326 (l == LogLevel_Trace && !loggingContext_->traceEnabled_))
327 // the mutex to speed-up things. The stream is set to "/dev/null" 327 {
328 // This logging level is disabled, directly exit and unlock
329 // the mutex to speed-up things. The stream is set to "/dev/null"
330 lock_.unlock();
331 return;
332 }
333
334 // Compute the header of the line, temporary release the lock as
335 // this is a time-consuming operation
328 lock_.unlock(); 336 lock_.unlock();
329 return; 337 std::string header;
330 } 338
331 339 {
332 // Compute the header of the line, temporary release the lock as 340 boost::filesystem::path path(file);
333 // this is a time-consuming operation 341 boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
334 lock_.unlock(); 342 boost::posix_time::time_duration duration = now.time_of_day();
335 std::string header; 343
336 344 /**
337 { 345 From Google Log documentation:
338 boost::filesystem::path path(file); 346
339 boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time(); 347 "Log lines have this form:
340 boost::posix_time::time_duration duration = now.time_of_day(); 348
341 349 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
342 /** 350
343 From Google Log documentation: 351 where the fields are defined as follows:
344 352
345 "Log lines have this form: 353 L A single character, representing the log level (eg 'I' for INFO)
346 354 mm The month (zero padded; ie May is '05')
347 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... 355 dd The day (zero padded)
348 356 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
349 where the fields are defined as follows: 357 threadid The space-padded thread ID as returned by GetTID() (this matches the PID on Linux)
350 358 file The file name
351 L A single character, representing the log level (eg 'I' for INFO) 359 line The line number
352 mm The month (zero padded; ie May is '05') 360 msg The user-supplied message"
353 dd The day (zero padded) 361
354 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds 362 In this implementation, "threadid" is not printed.
355 threadid The space-padded thread ID as returned by GetTID() (this matches the PID on Linux) 363 **/
356 file The file name 364
357 line The line number 365 char date[32];
358 msg The user-supplied message" 366 sprintf(date, "%c%02d%02d %02d:%02d:%02d.%06d ",
359 367 level[0],
360 In this implementation, "threadid" is not printed. 368 now.date().month().as_number(),
361 **/ 369 now.date().day().as_number(),
362 370 duration.hours(),
363 char date[32]; 371 duration.minutes(),
364 sprintf(date, "%c%02d%02d %02d:%02d:%02d.%06d ", 372 duration.seconds(),
365 level[0], 373 static_cast<int>(duration.fractional_seconds()));
366 now.date().month().as_number(), 374
367 now.date().day().as_number(), 375 header = std::string(date) + path.filename().string() + ":" + boost::lexical_cast<std::string>(line) + "] ";
368 duration.hours(), 376 }
369 duration.minutes(), 377
370 duration.seconds(), 378
371 static_cast<int>(duration.fractional_seconds())); 379 // The header is computed, we now re-lock the mutex to access
372 380 // the stream objects. Pay attention that "loggingContext_",
373 header = std::string(date) + path.filename().string() + ":" + boost::lexical_cast<std::string>(line) + "] "; 381 // "infoEnabled_" or "traceEnabled_" might have changed while
374 } 382 // the mutex was unlocked.
375 383 lock_.lock();
376 384
377 // The header is computed, we now re-lock the mutex to access 385 if (loggingContext_.get() == NULL)
378 // the stream objects. Pay attention that "loggingContext_", 386 {
379 // "infoEnabled_" or "traceEnabled_" might have changed while 387 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n");
380 // the mutex was unlocked. 388 return;
381 lock_.lock(); 389 }
382 390
383 if (loggingContext_.get() == NULL) 391 switch (l)
384 { 392 {
385 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); 393 case LogLevel_Error:
386 return; 394 stream_ = loggingContext_->error_;
387 } 395 break;
388 396
389 switch (l) 397 case LogLevel_Warning:
390 { 398 stream_ = loggingContext_->warning_;
391 case LogLevel_Error: 399 break;
392 stream_ = loggingContext_->error_; 400
393 break; 401 case LogLevel_Info:
394 402 if (loggingContext_->infoEnabled_)
395 case LogLevel_Warning: 403 {
396 stream_ = loggingContext_->warning_; 404 stream_ = loggingContext_->info_;
397 break; 405 }
398 406
399 case LogLevel_Info: 407 break;
400 if (loggingContext_->infoEnabled_) 408
401 { 409 case LogLevel_Trace:
402 stream_ = loggingContext_->info_; 410 if (loggingContext_->traceEnabled_)
403 } 411 {
404 412 stream_ = loggingContext_->info_;
405 break; 413 }
406 414
407 case LogLevel_Trace: 415 break;
408 if (loggingContext_->traceEnabled_) 416
409 { 417 default:
410 stream_ = loggingContext_->info_; 418 throw OrthancException(ErrorCode_InternalError);
411 } 419 }
412 420
413 break; 421 if (stream_ == &null_)
414 422 {
415 default: 423 // The logging is disabled for this level. The stream is the
416 throw OrthancException(ErrorCode_InternalError); 424 // "null_" member of this object, so we can release the global
417 } 425 // mutex.
418 426 lock_.unlock();
419 if (stream_ == &null_) 427 }
420 { 428
421 // The logging is disabled for this level. The stream is the 429 (*stream_) << header;
422 // "null_" member of this object, so we can release the global 430 }
423 // mutex. 431 catch (...)
424 lock_.unlock(); 432 {
425 } 433 // Something is going really wrong, probably running out of
426 434 // memory. Fallback to a degraded mode.
427 (*stream_) << header; 435 stream_ = loggingContext_->error_;
436 (*stream_) << "E???? ??:??:??.?????? ] ";
437 }
428 } 438 }
429 439
430 440
431 InternalLogger::~InternalLogger() 441 InternalLogger::~InternalLogger()
432 { 442 {