< prev index next >

src/share/vm/utilities/debug.cpp

Print this page
rev 7752 : 8065895: Synchronous signals during error reporting may terminate or hang VM process
Contributed-by: stuefe
Reviewed-by: dholmes


 299       VMError err(message);
 300       err.report_java_out_of_memory();
 301     }
 302   }
 303 }
 304 
 305 static bool error_reported = false;
 306 
 307 // call this when the VM is dying--it might loosen some asserts
 308 void set_error_reported() {
 309   error_reported = true;
 310 }
 311 
 312 bool is_error_reported() {
 313     return error_reported;
 314 }
 315 
 316 #ifndef PRODUCT
 317 #include <signal.h>
 318 






































 319 void test_error_handler() {
 320   uintx test_num = ErrorHandlerTest;
 321   if (test_num == 0) return;



 322 
 323   // If asserts are disabled, use the corresponding guarantee instead.
 324   size_t n = test_num;
 325   NOT_DEBUG(if (n <= 2) n += 2);
 326 
 327   const char* const str = "hello";
 328   const size_t      num = (size_t)os::vm_page_size();
 329 
 330   const char* const eol = os::line_separator();
 331   const char* const msg = "this message should be truncated during formatting";
 332   char * const dataPtr = NULL;  // bad data pointer
 333   const void (*funcPtr)(void) = (const void(*)()) 0xF;  // bad function pointer
 334 
 335   // Keep this in sync with test/runtime/6888954/vmerrors.sh.
 336   switch (n) {
 337     case  1: vmassert(str == NULL, "expected null");
 338     case  2: vmassert(num == 1023 && *str == 'X',
 339                       err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
 340     case  3: guarantee(str == NULL, "expected null");
 341     case  4: guarantee(num == 1023 && *str == 'X',
 342                        err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
 343     case  5: fatal("expected null");
 344     case  6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
 345     case  7: fatal(err_msg("%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
 346                            "%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
 347                            "%s%s#    %s%s#    %s%s#    %s%s#    %s",
 348                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
 349                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
 350                            msg, eol, msg, eol, msg, eol, msg, eol, msg));
 351     case  8: vm_exit_out_of_memory(num, OOM_MALLOC_ERROR, "ChunkPool::allocate");
 352     case  9: ShouldNotCallThis();
 353     case 10: ShouldNotReachHere();
 354     case 11: Unimplemented();
 355     // There's no guarantee the bad data pointer will crash us
 356     // so "break" out to the ShouldNotReachHere().
 357     case 12: *dataPtr = '\0'; break;
 358     // There's no guarantee the bad function pointer will crash us
 359     // so "break" out to the ShouldNotReachHere().
 360     case 13: (*funcPtr)(); break;


 361 
 362     default: tty->print_cr("ERROR: %d: unexpected test_num value.", n);
 363   }
 364   ShouldNotReachHere();
 365 }
 366 #endif // !PRODUCT
 367 
 368 // ------ helper functions for debugging go here ------------
 369 
 370 // All debug entries should be wrapped with a stack allocated
 371 // Command object. It makes sure a resource mark is set and
 372 // flushes the logfile to prevent file sharing problems.
 373 
 374 class Command : public StackObj {
 375  private:
 376   ResourceMark rm;
 377   ResetNoHandleMark rnhm;
 378   HandleMark   hm;
 379   bool debug_save;
 380  public:
 381   static int level;
 382   Command(const char* str) {




 299       VMError err(message);
 300       err.report_java_out_of_memory();
 301     }
 302   }
 303 }
 304 
 305 static bool error_reported = false;
 306 
 307 // call this when the VM is dying--it might loosen some asserts
 308 void set_error_reported() {
 309   error_reported = true;
 310 }
 311 
 312 bool is_error_reported() {
 313     return error_reported;
 314 }
 315 
 316 #ifndef PRODUCT
 317 #include <signal.h>
 318 
 319 typedef void (*voidfun_t)();
 320 // Crash with an authentic sigfpe
 321 static void crash_with_sigfpe() {
 322   // generate a native synchronous SIGFPE where possible;
 323   // if that did not cause a signal (e.g. on ppc), just
 324   // raise the signal.
 325   volatile int x = 0;
 326   volatile int y = 1/x;
 327   printf("%d", y);
 328 #ifndef _WIN32
 329   raise(SIGFPE);
 330 #endif
 331 } // end: crash_with_sigfpe
 332 
 333 // crash with sigsegv at non-null address.
 334 static void crash_with_segfault() {
 335 
 336   char* const crash_addr = (char*) get_segfault_address();
 337 
 338   tty->print_cr("will access address " PTR_FORMAT
 339     ", which should cause a SIGSEGV.", crash_addr);
 340   tty->flush();
 341 
 342   *crash_addr = 'X';
 343 
 344 } // end: crash_with_segfault
 345 
 346 // returns an address which is guaranteed to generate a SIGSEGV on read,
 347 // for test purposes, which is not NULL and contains bits in every word
 348 void* get_segfault_address() {
 349   return (void*)
 350 #ifdef _LP64
 351     0xABC0000000000ABCULL;
 352 #else
 353     0x00000ABC;
 354 #endif
 355 }
 356 
 357 void test_error_handler() {
 358   controlled_crash(ErrorHandlerTest);
 359 }
 360 
 361 void controlled_crash(int how) {
 362   if (how == 0) return;
 363 
 364   // If asserts are disabled, use the corresponding guarantee instead.
 365   NOT_DEBUG(if (how <= 2) how += 2);

 366 
 367   const char* const str = "hello";
 368   const size_t      num = (size_t)os::vm_page_size();
 369 
 370   const char* const eol = os::line_separator();
 371   const char* const msg = "this message should be truncated during formatting";
 372   char * const dataPtr = NULL;  // bad data pointer
 373   const void (*funcPtr)(void) = (const void(*)()) 0xF;  // bad function pointer
 374 
 375   // Keep this in sync with test/runtime/6888954/vmerrors.sh.
 376   switch (how) {
 377     case  1: vmassert(str == NULL, "expected null");
 378     case  2: vmassert(num == 1023 && *str == 'X',
 379                       err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
 380     case  3: guarantee(str == NULL, "expected null");
 381     case  4: guarantee(num == 1023 && *str == 'X',
 382                        err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
 383     case  5: fatal("expected null");
 384     case  6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
 385     case  7: fatal(err_msg("%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
 386                            "%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
 387                            "%s%s#    %s%s#    %s%s#    %s%s#    %s",
 388                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
 389                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
 390                            msg, eol, msg, eol, msg, eol, msg, eol, msg));
 391     case  8: vm_exit_out_of_memory(num, OOM_MALLOC_ERROR, "ChunkPool::allocate");
 392     case  9: ShouldNotCallThis();
 393     case 10: ShouldNotReachHere();
 394     case 11: Unimplemented();
 395     // There's no guarantee the bad data pointer will crash us
 396     // so "break" out to the ShouldNotReachHere().
 397     case 12: *dataPtr = '\0'; break;
 398     // There's no guarantee the bad function pointer will crash us
 399     // so "break" out to the ShouldNotReachHere().
 400     case 13: (*funcPtr)(); break;
 401     case 14: crash_with_segfault(); break;
 402     case 15: crash_with_sigfpe(); break;
 403 
 404     default: tty->print_cr("ERROR: %d: unexpected test_num value.", how);
 405   }
 406   ShouldNotReachHere();
 407 }
 408 #endif // !PRODUCT
 409 
 410 // ------ helper functions for debugging go here ------------
 411 
 412 // All debug entries should be wrapped with a stack allocated
 413 // Command object. It makes sure a resource mark is set and
 414 // flushes the logfile to prevent file sharing problems.
 415 
 416 class Command : public StackObj {
 417  private:
 418   ResourceMark rm;
 419   ResetNoHandleMark rnhm;
 420   HandleMark   hm;
 421   bool debug_save;
 422  public:
 423   static int level;
 424   Command(const char* str) {


< prev index next >