ATLAS Offline Software
SealSignal.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
20 //<<<<<< INCLUDES >>>>>>
21 
22 #include "CxxUtils/SealCommon.h" // wlav
23 #include "CxxUtils/SealSignal.h" // wlav
24 #include "CxxUtils/SealDebug.h" // wlav
25 #include "CxxUtils/SealSharedLib.h" // wlav
26 // wlav copied from SealBase/sysapi/Signal.h
31 static const int SIGNAL_MESSAGE_BUFSIZE = 2048;
32 // end copy from SealBase/sysapi/Signal.h
33 #include <cassert>
34 #include <cstring>
35 #include <cerrno> // wlav
36 #include <cstdio> // wlav
37 #include <cstdlib> // sss
38 #include <sys/stat.h>
39 #include <unistd.h> // krasznaa
40 
41 #if defined(__aarch64__) && defined(__linux)
42 # include "arm_helpers.h"
43 #endif
44 
45 /* http://dmawww.epfl.ch/ebt-bin/nph-dweb/dynaweb/SGI_Developer/
46  T_IRIX_Prog/@Generic__BookTextView/7525
47 
48  POSIX SVR4 BSD 4.2
49  =========================================================
50  sigaction(2) sigset(2) sigvec(3)
51  sigsetops(3) signal(2) signal(3)
52  sigaltstack(2)
53 
54  sigqueue(2) sigsend(2) kill(3)
55  kill(2) kill(2) killpg(3)
56  pthread_kill(3P)
57 
58  sigprocmask(2) sighold(2) sigblock(3)
59  pthread_sigmask(3P) sigrelse(2) sigsetmask(3)
60 
61  sigpending(2) n.a. n.a.
62 
63  sigsuspend(2) sigpause(2) sigpause(3)
64 
65  sigwait(2) n.a. n.a.
66  sigwaitinfo(2)
67  sigtimedwait(2)
68 */
69 
70 
71 // wlav copied from SealBase/src/ProcessInfo.cpp
73 static pid_t
74 ProcessInfo__pid (void)
75 {
76 #ifdef _WIN32
77  return GetCurrentProcessId ();
78 #else
79  return ::getpid ();
80 #endif
81 }
82 
84 static pid_t
85 ProcessInfo__ppid (void)
86 {
87 #ifdef _WIN32
88  PROCESS_BASIC_INFORMATION pbi;
89  if (NtQueryInformationProcess (GetCurrentProcess(),ProcessBasicInformation,
90  &pbi, sizeof (pbi), 0) == STATUS_SUCCESS)
91  return pbi.InheritedFromUniqueProcessId;
92 
93  // FIXME: throw systemerror!
94  assert (false);
95  return -1;
96 #else
97  return ::getppid ();
98 #endif
99 }
100 
101 
102 //namespace seal { wlav
103 namespace Athena { // wlav
104 //<<<<<< PRIVATE DEFINES >>>>>>
105 //<<<<<< PRIVATE CONSTANTS >>>>>>
106 //<<<<<< PRIVATE TYPES >>>>>>
107 
109 extern "C" { typedef void (*DummyHandlerType) (int); }
110 
111 //<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>>
112 
118 static SharedLibrary::InfoHandler *SignalDumpCallback = 0;
119 
120 //<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>>
121 //<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>>
122 
125 bool Signal::s_crashed = false;
126 
129 int Signal::s_inFatal = 0;
130 
132 // This would in principle be better as a thread_local, but then
133 // accessing it might allocate memory, which we don't to happen
134 // during error handling.
135 // Doing it like this should be good enough.
136 std::atomic<unsigned long> Signal::s_lastSP (0);
137 
139 const char *Signal::s_applicationName = 0;
140 
143 
146 
149 
151 unsigned Signal::s_fatalOptions = 0;
152 
155 
156 #if !HAVE_POSIX_SIGNALS || !SA_SIGINFO
157 
164 #endif
165 
166 //<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>>
167 
174 static void
175 SignalDumpLibs (const SharedLibrary::LibraryInfo &info, IOFD fd)
176 {
177  const int buf_size = BitTraits<unsigned long>::HexDigits + 5;
178  char buf [buf_size];
179  MYWRITE (fd, buf, snprintf (buf, buf_size, " 0x%08lx ", info.m_text_start));
180  MYWRITE (fd, info.m_filename, strlen (info.m_filename));
181  MYWRITE (fd, "\n", 1);
182 }
183 
184 #ifdef _WIN32
185 
187 static LONG CALLBACK
188 SEHFatal (PEXCEPTION_POINTERS info)
189 {
190  Signal::fatal (SIGABRT, info->ExceptionRecord, info->ContextRecord);
191  return EXCEPTION_EXECUTE_HANDLER;
192 }
193 #endif // _WIN32
194 
195 //<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>>
196 //<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>>
197 
198 #if !HAVE_POSIX_SIGNALS
199 
202 void
204 {
205  assert (sig > 0 && sig < NSIG);
206  assert (s_trampolines [sig]);
207  siginfo_t info;
208  memset (&info, 0, sizeof (info));
209  s_trampolines [sig] (sig, &info, 0);
210 }
211 #endif
212 
215 const char *
217 {
218 #if HAVE_STRSIGNAL
219  return strsignal (sig);
220 #elif HAVE_SYS_SIGLIST
221  return sys_siglist [sig];
222 #else
223  // This is not thread safe. But if you have threads, you probably
224  // have strsignal() as well (FIXME: check WIN32).
225  static const int buf_size = 8 + BitTraits<int>::Digits;
226  static char buf [NSIG] [buf_size];
227  if (! buf [sig][0])
228  snprintf (buf [sig], buf_size, "Signal %d", sig);
229  return buf [sig];
230 #endif
231 }
232 
236 Signal::handler (int sig, sigset_t *mask /* = 0 */)
237 {
238  assert (sig > 0 && sig < NSIG);
239 
240  // Get the handler
241 #if HAVE_POSIX_SIGNALS
242  struct sigaction old;
243  STDC::memset (&old, 0, sizeof (old));
244  if (sigaction (sig, &old, 0) == 0)
245  {
246  if (mask)
247  *mask = old.sa_mask;
248  return (HandlerType) (void*) old.sa_handler;
249  }
250  else
251  return (HandlerType) (void*)SIG_ERR;
252 #else // ! HAVE_POSIX_SIGNALS
253  HandlerType old = (HandlerType) signal (sig, SIG_DFL);
255  return old;
256 #endif // HAVE_POSIX_SIGNALS
257 }
258 
277 Signal::handle (int sig, HandlerType handler, const sigset_t *blockMask /*=0*/)
278 {
279  assert (sig > 0 && sig < NSIG);
280  // LOG (0, trace, LFsignal, "[" << sig << "] (" << name (sig) << ") = "
281  // << (void *) handler << '\n'); // wlav
282 
283  HandlerType oldhandler;
284 #if !HAVE_POSIX_SIGNALS || !SA_SIGINFO
285  // Switch to using trampoline if we don't have the necessary
286  // arguments. FIXME: multiple threads; WIN32?
287  oldhandler = s_trampolines [sig];
288  if (handler == (HandlerType) SIG_IGN || handler == (HandlerType) SIG_DFL)
289  s_trampolines [sig] = 0;
290  else
291  {
294  }
295 #endif
296 
297  // Set the handler
298 #if HAVE_POSIX_SIGNALS
299  struct sigaction old, act;
300  STDC::memset (&act, 0, sizeof (act));
301  STDC::memset (&old, 0, sizeof (old));
302  act.sa_flags = SA_RESTART | SA_SIGINFO;
303  act.sa_sigaction = handler;
304  sigemptyset (&act.sa_mask);
305  if (blockMask)
306  act.sa_mask = *blockMask;
307  else if (sigaction (sig, &old, 0) == 0)
308  act.sa_mask = old.sa_mask;
309  else
310  sigemptyset (&act.sa_mask);
311 
312  // There isn't much we can do to check the return status. We get
313  // called in all sorts fragile places like signal handlers, and
314  // those are not the place for throwing exceptions or asserting.
315  if (sigaction (sig, &act, &old) == -1)
316  return (HandlerType) (void*)SIG_ERR;
317  oldhandler = (HandlerType) old.sa_sigaction;
318 #else // ! HAVE_POSIX_SIGNALS
320 #endif // HAVE_POSIX_SIGNALS
321  return oldhandler;
322 }
323 
325 void
327 { handle (sig, (HandlerType) (void*)SIG_DFL); }
328 
330 void
332 { handle (sig, (HandlerType) (void*)SIG_IGN); }
333 
337 void
338 Signal::block (int sig, bool sense)
339 {
340 #if HAVE_POSIX_SIGNALS
341  // FIXME: threads -- need to use pthread_sigmask
342  sigset_t mask;
343  sigemptyset (&mask);
344  sigaddset (&mask, sig);
345  block (&mask, sense);
346 #endif
347 }
348 
352 void
353 Signal::block (const sigset_t *mask, bool sense)
354 {
355 #if HAVE_POSIX_SIGNALS
356  // FIXME: threads -- need to use pthread_sigmask
357  sigprocmask (sense ? SIG_BLOCK : SIG_UNBLOCK, mask, 0);
358 #endif
359 }
360 
364 void
365 Signal::mask (const sigset_t *mask, sigset_t *old /* = 0 */)
366 {
367 #if HAVE_POSIX_SIGNALS
368  // FIXME: threads -- need to use pthread_sigmask
369  sigprocmask (SIG_SETMASK, mask, old);
370 #endif
371 }
372 
374 
376 int
378 {
379 #if HAVE_RAISE
380  return ::raise (sig);
381 #else
382  return ::kill (getpid (), sig);
383 #endif
384 }
385 
388 int
390 {
391  // FIXME: sending signals to threads?
392 #ifndef _WIN32
393  return ::kill (process, sig);
394 #else
395  return 0;
396 #endif
397 }
398 
401 #if HAVE_POSIX_RT_SIGNALS
402 int
403 Signal::queue (pid_t process, int sig, int value /* = 0 */)
404 {
405  union sigval v;
406  v.sival_int = value;
407  return sigqueue (process, sig, v);
408 }
409 #else
410 int
411 Signal::queue (pid_t /*process*/, int /*sig*/, int /*value = 0 */)
412 {
413  return 0;
414 }
415 #endif
416 
419 #if HAVE_POSIX_RT_SIGNALS
420 int
421 Signal::queue (pid_t process, int sig, void *value)
422 {
423  union sigval v;
424  v.sival_ptr = value;
425  return sigqueue (process, sig, v);
426 }
427 #else
428 int
429 Signal::queue (pid_t /*process*/, int /*sig*/, void */*value*/)
430 {
431  return 0;
432 }
433 #endif
434 
438 #if HAVE_POSIX_RT_SIGNALS
439 int
440 Signal::queue (int sig, int value /* = 0 */)
441 {
442  return queue (getpid (), sig, value);
443 }
444 #else
445 int
446 Signal::queue (int /*sig*/, int /*value = 0 */)
447 {
448  return 0;
449 }
450 #endif
451 
455 #if HAVE_POSIX_RT_SIGNALS
456 int
457 Signal::queue (int sig, void *value)
458 {
459  return queue (getpid (), sig, value);
460 }
461 #else
462 int
463 Signal::queue (int /*sig*/, void */*value*/)
464 {
465  return 0;
466 }
467 #endif
468 
470 bool
472 { sigset_t s; pending (&s); return sigismember (&s, sig); }
473 
475 #if HAVE_POSIX_SIGNALS
476 void
478 {
479  assert (mask);
480  sigpending (mask);
481 }
482 #else
483 void
485 {
486 }
487 #endif
488 
491 #if HAVE_POSIX_SIGNALS
492 void
494 {
495  assert (mask);
496  sigsuspend (mask);
497 }
498 #else
499 void
500 Signal::suspend (const sigset_t */*mask*/)
501 {
502 }
503 #endif
504 
514 bool
515 Signal::wait (int sig, siginfo_t *info /* = 0 */, long msecs /* = -1 */)
516 {
517  sigset_t s;
518  sigemptyset (&s);
519  sigaddset (&s, sig);
520  // cppcheck-suppress uninitvar
521  return wait (&s, info, msecs) == sig;
522 }
523 
535 #if HAVE_POSIX_RT_SIGNALS
536 int
537 Signal::wait (const sigset_t *mask,
538  siginfo_t *info /* = 0 */,
539  long msecs /* = -1 */)
540 {
541  siginfo_t myinfo;
542  timespec ts;
543 
544  if (msecs < 0)
545  sigwaitinfo (mask, &myinfo);
546  else
547  {
548  ts.tv_sec = msecs / 1000;
549  ts.tv_nsec = (msecs % 1000) * 1000000;
550  if (sigtimedwait (mask, &myinfo, &ts) == -1 && errno == EINTR)
551  // FIXME: deal with other error codes (NB: EAGAIN == timed out)
552  return -1;
553  }
554 
555  if (info)
556  *info = myinfo;
557 
558  return myinfo.si_signo;
559 }
560 #else
561 int
562 Signal::wait (const sigset_t */*mask*/,
563  siginfo_t */*info = 0 */,
564  long /*msecs = -1 */)
565 {
566  return 0;
567 }
568 #endif
569 
571 /* Install #quit() as the handler for quitting-related signals.
572 
573  This method installs #quit() as the handler for quitting-related
574  signals such as SIGHUP, SIGTERM and SIGQUIT. Upon signal delivery
575  @a hook will be invoked; if it returns @c true, #quit() proceeds to
576  exit by re-raising the signal (in order to make the program's exit
577  status reflect the signal exit). If the @a hook returns @c false,
578  the signal is effectively ignored. Note however that certain
579  options to #fatal() also cause the quit hook to be invoked. */
580 void
581 Signal::handleQuit ATLAS_NOT_THREAD_SAFE (QuitHook hook /* = 0 */)
582 {
583  static int hups [] = {
584 #ifdef SIGHUP
585  // hang up (lost terminal or process group leader)
586  SIGHUP,
587 #endif
588 #ifdef SIGTERM
589  // terminate (e.g. system going down)
590  SIGTERM,
591 #endif
592 #ifdef SIGQUIT
593  // user request to quit and leave debuggable state (from quit
594  // key on controlling terminal)
595  SIGQUIT,
596 #endif
597  -1
598  };
599 
600  if (hook)
601  s_quitHook = hook;
602 
603  for (unsigned sig = 0; hups [sig] != -1; ++sig)
604  handle (hups [sig], quit);
605 }
606 
645 void
646 Signal::handleFatal ATLAS_NOT_THREAD_SAFE (const char *applicationName /* = 0 */,
647  IOFD fd /* = IOFD_INVALID */,
648  FatalHook hook /* = 0 */,
649  FatalReturn mainreturn /* = 0 */,
650  unsigned options /* = FATAL_DEFAULT */)
651 {
652  // FIXME: Provide means to install handlers for fatal signals that
653  // an application has requested and app was supposed to register a
654  // handler before making the request? (So that if the app handler
655  // is not installed for some reason, an internal error hook can
656  // run?) Such fatal signals include:
657  // - SIGPIPE: read or write to broken pipe; child died
658  // (read or write to socket with ASYNC io?)
659  // - SIGLOST: lost a resource (e.g., lock on nfs server reboot)
660  // - SIGALRM: interval timer elapsed
661  // - SIGUSR1, SIGUSR2
662  // - SIGPOLL: pollable streams device events
663  // - SIGIO: i/o possible (from async i/o)
664  // - SIGVTALRM: virtual timer expired
665  // - SIGPROF: profiling timer expired
666  // - SIGRTMIN - SIGRTMAX: POSIX real-time signals
667  //
668  // Some of these the application should probably just #block()
669  // (e.g. SIGPIPE). Some of them the app should block and then
670  // wait or poll for events (SIGPOLL, SIGIO, possibly SIGALRM, the
671  // real-time signals if they are used).
672 
673  static const int hups [] = {
674 #ifdef SIGHUP
675  SIGHUP, // hang up (lost terminal or process group leader)
676 #endif
677 #ifdef SIGTERM
678  SIGTERM, // terminate (e.g. system going down)
679 #endif
680 #ifdef SIGQUIT
681  SIGQUIT, /* user request to quit and leave debuggable
682  state (from quit key on controlling
683  terminal) */
684 
685 #endif
686  -1
687  };
688 
689  static int fatals [] = {
690 #ifdef SIGFPE
691  SIGFPE, // arithmetic exception
692 #endif
693 #ifdef SIGILL
694  SIGILL, // illegal instruction
695 #endif
696 #ifdef SIGSEGV
697  SIGSEGV, // illegal address
698 #endif
699 #ifdef SIGBUS
700  SIGBUS, // hardware exception
701 #endif
702 #ifdef SIGIOT
703  SIGIOT, /* IOT trap. Before SIGABRT so that if SIGIOT
704  == SIGABRT then SIGABRT overrides SIGIOT;
705  SIGABRT is in ISO C and POSIX.1, SIGIOT is
706  not. */
707 #endif
708 #ifdef SIGABRT
709  SIGABRT, // abort
710 
711 #endif
712 #ifdef SIGTRAP
713  SIGTRAP, // trace/breakpoint reached
714 #endif
715 #ifdef SIGEMT
716  SIGEMT, // emulation trap (may be used by profiler?)
717 #endif
718 #ifdef SIGSYS
719  SIGSYS, // invalid system call
720 #endif
721 #ifdef SIGXCPU
722  SIGXCPU, // cpu time limit exceeded
723 #endif
724 #ifdef SIGXFSZ
725  SIGXFSZ, // file size limit exceeded
726 #endif
727  -1
728  };
729 
730  // Make sure `strsignal' is properly initialised.
731  name (1);
732 
733  // Remember app name if specified
734  if (applicationName && *applicationName)
735  s_applicationName = applicationName;
736 
737  // Automatically initialise s_fatalFd on first access
738  if (s_fatalFd == IOFD_INVALID)
739  s_fatalFd = STDERR_HANDLE;
740 
741  // Remember the fatal output fd if defined
742  if (fd != IOFD_INVALID)
743  s_fatalFd = fd;
744 
745  // Now that we know the fd, setup a callback for dumping shared
746  // libraries via #SignalDumpLibs. This avoids having to allocate
747  // memory for the callback implementation in the middle of a fatal
748  // signal, and on the other hand avoids a global object which
749  // might not be initialised yet.
750  delete SignalDumpCallback;
751  SignalDumpCallback = new SharedLibrary::InfoHandler
752  (CreateCallback (&SignalDumpLibs, s_fatalFd));
753 
754  // Remember the hooks if specified
755  if (hook)
756  s_fatalHook = hook;
757 
758  if (mainreturn)
759  s_fatalReturn = mainreturn;
760 
761  // Remember the new options
762  s_fatalOptions = options;
763 
764  // Signal::fatal() requires this, otherwise weird things can happen.
765  // Programs not wanting to return to main should set FATAL_AUTO_EXIT.
766  assert (s_fatalReturn || (s_fatalOptions & FATAL_AUTO_EXIT));
767 
768  // Install signal handlers.
769  if (options & FATAL_ON_QUIT)
770  for (unsigned sig = 0; hups [sig] != -1; ++sig)
771  handle (hups [sig], fatal);
772 
773  for (unsigned sig = 0; fatals [sig] != -1; ++sig)
774  handle (fatals [sig], fatal);
775 
776 #ifdef SIGINT
777  // interrupt key from controlling terminal
778  if (options & FATAL_ON_INT)
779  handle (SIGINT, fatal);
780 #endif
781 
782 #ifdef SIGUSR1
783  // program-defined signals SIGUSR1 and SIGUSR2
784  if (options & USR1_DUMP_CORE)
785  handle (SIGUSR1, (HandlerType) DebugAids::coredump);
786 #endif
787 
788 #ifdef _WIN32
789  SetUnhandledExceptionFilter (&SEHFatal);
790 #endif
791 }
792 
816 void
817 Signal::quit ATLAS_NOT_THREAD_SAFE (int sig, siginfo_t *info, void *x)
818 {
819  // Quit if no hook has been registered: we are coming in via
820  // FATAL_AUTO_EXIT in fatal and the application did not call
821  // handleQuit.
822  if (! s_quitHook || (*s_quitHook) (sig, info, x))
823  {
824  // Reactivate the default signal handling behaviour for this
825  // signal, which is to terminate the application one way or
826  // the other. Then exit through the signal. This makes the
827  // process exit status correct.
828  revert (sig);
829  raise (sig);
830  }
831 }
832 
894 void
895 Signal::fatal ATLAS_NOT_THREAD_SAFE (int sig, siginfo_t *info, void *x)
896 {
897  assert (s_fatalReturn || (s_fatalOptions & FATAL_AUTO_EXIT));
898 
899 #if !HAVE_POSIX_SIGNALS
900  // Reinstall the handler for poor SVR4 systems that reset signal
901  // handlers upon delivery. I doubt this code ever gets run on a
902  // system without sigaction, but let's be ultracorrect.
903  handle (sig, &fatal);
904 #endif
905 
906  // Unblock the signal itself so that if we get this again, we'll
907  // enter the handler again. Otherwise if the user's hook or
908  // fatalDump has trouble, we'll hang until someone sends us a
909  // different signal.
910  block (sig, false);
911 
912  // Check that we aren't going too deep in fatal handlers. We
913  // allow a little nesting as sometimes the handlers gets tangled
914  // up producing a dump, but after an extra signal can finish. If
915  // the nesting exceeds our limit, we give up and exit with default
916  // signal behaviour: no hooks any more, they've had their chance.
917  if (++s_inFatal > 4)
918  {
919  revert (sig);
920  raise (sig);
921  }
922 
923  // Check if this signal is fatal. If so, indicate we've crashed.
924  bool fatal = (sig != SIGINT) || (s_fatalOptions & FATAL_ON_INT);
925  if (fatal)
926  s_crashed = true;
927 
928  // Create core file if requested (without interrupting the program)
929  bool haveCore = false;
930  if (s_inFatal == 1 && fatal && (s_fatalOptions & FATAL_DUMP_CORE))
931  {
933 #ifndef _WIN32
934  struct stat st;
935  haveCore = (::stat ("core", &st) == 0
936  && S_ISREG (st.st_mode)
937  && st.st_size > 0);
938 #endif
939  }
940 
941  // Check if we are done -- if so, commit a suicide, it should be
942  // painless. s_fatalHook and s_quitHook ought to be protected
943  // from infinitely looping signals, either using #fatalLevel() or
944  // deregistering themselves on the first call.
945  if (s_inFatal > 1 || (s_fatalOptions & FATAL_AUTO_EXIT))
946  {
947  if (s_fatalHook
948  ? (*s_fatalHook) (haveCore ? -sig : sig, info, x)
949  : fatalDump (haveCore ? -sig : sig, info, x))
950  // Suicide: re-raise the signal; we'll die as we return.
951  quit (sig, info, x);
952  return;
953  }
954 
955  // Prevent possible infinite recursion...
956  if (!s_fatalReturn) // sss
957  std::abort(); // sss
958 
959  // Return to main program.
960  --s_inFatal;
961 
962  (*s_fatalReturn) (haveCore ? -sig : sig, info, x);
963 }
964 
967 const char *
969 {
970  static const struct { int sig; int code; const char *desc; } infos [] = {
971 #if HAVE_POSIX_SIGNALS
972  { -1, SI_USER, "user sent: kill, sigsend or raise" },
973 # ifdef SI_KERNEL
974  { -1, SI_KERNEL, "kernel" },
975 # endif
976  { -1, SI_QUEUE, "sigqueue" },
977  { -1, SI_TIMER, "timer expired" },
978  { -1, SI_MESGQ, "mesq state changed" },
979  { -1, SI_ASYNCIO, "AIO completed" },
980 # ifdef SI_SIGIO // not solaris
981  { -1, SI_SIGIO, "queued SIGIO" },
982 # endif
983 
984 # ifdef ILL_NOOP // darwin
985  { SIGILL, ILL_NOOP, "noop" },
986 # endif
987  { SIGILL, ILL_ILLOPC, "illegal opcode" },
988 # ifdef ILL_ILLOPN // not darwin
989  { SIGILL, ILL_ILLOPN, "illegal operand" },
990 # endif
991 # ifdef ILL_ILLADR // not darwin
992  { SIGILL, ILL_ILLADR, "illegal addressing mode" },
993 # endif
994  { SIGILL, ILL_ILLTRP, "illegal trap" },
995  { SIGILL, ILL_PRVOPC, "privileged opcode" },
996 # ifdef ILL_PRVREG // not darwin
997  { SIGILL, ILL_PRVREG, "privileged register" },
998 # endif
999 # ifdef ILL_COPROC // not darwin
1000  { SIGILL, ILL_COPROC, "coprocessor error" },
1001 # endif
1002 # ifdef ILL_BADSTK // not darwin
1003  { SIGILL, ILL_BADSTK, "internal stack error" },
1004 # endif
1005 
1006 # ifdef FPE_NOOP // darwin
1007  { SIGFPE, FPE_NOOP, "noop" },
1008 # endif
1009 # ifdef FPE_INTDIV // not darwin
1010  { SIGFPE, FPE_INTDIV, "integer divide by zero" },
1011 # endif
1012 # ifdef FPE_INTOVF // not darwin
1013  { SIGFPE, FPE_INTOVF, "integer overflow" },
1014 # endif
1015  { SIGFPE, FPE_FLTDIV, "floating point divide by zero" },
1016  { SIGFPE, FPE_FLTOVF, "floating point overflow" },
1017  { SIGFPE, FPE_FLTUND, "floating point underflow" },
1018  { SIGFPE, FPE_FLTRES, "floating point inexact result" },
1019  { SIGFPE, FPE_FLTINV, "floating point invalid operation" },
1020 # ifdef FPE_FLTSUB // not darwin
1021  { SIGFPE, FPE_FLTSUB, "subscript out of range" },
1022 # endif
1023 
1024 # ifdef SEGV_NOOP // darwin
1025  { SIGSEGV, SEGV_NOOP, "noop" },
1026 # endif
1027  { SIGSEGV, SEGV_MAPERR, "address not mapped to object" },
1028  { SIGSEGV, SEGV_ACCERR, "invalid permissions for mapped object" },
1029 
1030 # ifdef BUS_NOOP // darwin
1031  { SIGBUS, BUS_NOOP, "noop" },
1032 # endif
1033  { SIGBUS, BUS_ADRALN, "invalid address alignment" },
1034 # ifdef BUS_ADRERR // not darwin
1035  { SIGBUS, BUS_ADRERR, "non-existent physical address" },
1036 # endif
1037 # ifdef BUS_OBJERR // not darwin
1038  { SIGBUS, BUS_OBJERR, "object specific hardware error" },
1039 # endif
1040 
1041 # ifdef TRAP_BRKPT // not darwin
1042  { SIGTRAP, TRAP_BRKPT, "process break point" },
1043 # endif
1044 # ifdef TRAP_TRACE // not darwin
1045  { SIGTRAP, TRAP_TRACE, "process trace trap" },
1046 # endif
1047 
1048 # ifdef CLD_NOOP // darwin
1049  { SIGCHLD, CLD_NOOP, "noop" },
1050 # endif
1051  { SIGCHLD, CLD_EXITED, "child has exited" },
1052  { SIGCHLD, CLD_KILLED, "child was killed" },
1053  { SIGCHLD, CLD_DUMPED, "child terminated abnormally" },
1054  { SIGCHLD, CLD_TRAPPED, "traced child has trapped" },
1055  { SIGCHLD, CLD_STOPPED, "child has stopped" },
1056  { SIGCHLD, CLD_CONTINUED,"stopped child has continued" },
1057 
1058 # ifdef SIGPOLL // not darwin
1059  { SIGPOLL, POLL_IN, "data input available" },
1060  { SIGPOLL, POLL_OUT, "output buffers available" },
1061  { SIGPOLL, POLL_MSG, "input message available" },
1062  { SIGPOLL, POLL_ERR, "i/o error" },
1063  { SIGPOLL, POLL_PRI, "high priority input available" },
1064  { SIGPOLL, POLL_HUP, "device disconnected" },
1065 # endif
1066 #endif // HAVE_POSIX_SIGNALS
1067 
1068  { -1, -1, 0 }
1069  };
1070 
1071  for (unsigned i = 0; infos [i].desc; ++i)
1072  if ((infos [i].sig == -1 || infos [i].sig == sig)
1073  && infos [i].code == code)
1074  return infos [i].desc;
1075 
1076  return "*unknown reason*";
1077 }
1078 
1083 void
1084 Signal::dumpInfo (IOFD fd, char *buf, unsigned int buf_size, int sig, const siginfo_t *info)
1085 {
1086  if (! info)
1087  return;
1088 
1089 #ifdef _WIN32
1090 # define DOCODE(x) case x: name = #x
1091  // NB: siginfo_t == EXCEPTION_RECORD.
1092  const char *name = 0;
1093 
1094  switch (info->ExceptionCode)
1095  {
1096  DOCODE(STATUS_ABANDONED_WAIT_0);
1097  DOCODE(STATUS_ACCESS_VIOLATION);
1098  DOCODE(STATUS_ARRAY_BOUNDS_EXCEEDED);
1099  DOCODE(STATUS_BREAKPOINT);
1100  DOCODE(STATUS_CONTROL_C_EXIT);
1101  DOCODE(STATUS_DATATYPE_MISALIGNMENT);
1102  DOCODE(STATUS_FLOAT_DENORMAL_OPERAND);
1103  DOCODE(STATUS_FLOAT_DIVIDE_BY_ZERO);
1104  DOCODE(STATUS_FLOAT_INEXACT_RESULT);
1105  DOCODE(STATUS_FLOAT_INVALID_OPERATION);
1106  DOCODE(STATUS_FLOAT_OVERFLOW);
1107  DOCODE(STATUS_FLOAT_STACK_CHECK);
1108  DOCODE(STATUS_FLOAT_UNDERFLOW);
1109  DOCODE(STATUS_GUARD_PAGE_VIOLATION);
1110  DOCODE(STATUS_ILLEGAL_INSTRUCTION);
1111  DOCODE(STATUS_INTEGER_DIVIDE_BY_ZERO);
1112  DOCODE(STATUS_INTEGER_OVERFLOW);
1113  DOCODE(STATUS_INVALID_DISPOSITION);
1114  DOCODE(STATUS_IN_PAGE_ERROR);
1115  DOCODE(STATUS_NONCONTINUABLE_EXCEPTION);
1116  DOCODE(STATUS_NO_MEMORY);
1117  DOCODE(STATUS_PENDING);
1118  DOCODE(STATUS_PRIVILEGED_INSTRUCTION);
1119  DOCODE(STATUS_SINGLE_STEP);
1120  DOCODE(STATUS_STACK_OVERFLOW);
1121  DOCODE(STATUS_TIMEOUT);
1122  DOCODE(STATUS_USER_APC);
1123  DOCODE(STATUS_WAIT_0);
1124  }
1125  // -> DWORD ExceptionCode
1126  // -> DWORD ExceptionFlags
1127  // -> EXCEPTION_RECORD *ExceptionRecord
1128  // -> PVOID ExceptionAddress
1129  // -> DWORD NumberParameters
1130  // -> DWORD ExceptionInfo [MAX_PARAMETERS (15)]
1131  if (name)
1132  MYWRITE (fd, buf, snprintf (buf, buf_size, "Exception: %s\n", name));
1133  else
1134  MYWRITE (fd, buf, snprintf (buf, buf_size, "Exception %lu\n",
1135  info->ExceptionCode));
1136  MYWRITE (fd, buf, snprintf (buf, buf_size, " addr = %08lx", info->ExceptionAddress));
1137 
1138 #elif HAVE_POSIX_SIGNALS
1139  // These should always be set.
1140  MYWRITE (fd, buf, snprintf (buf, buf_size,
1141  " signo = %d, errno = %d, code = %d (%s)\n",
1142  info->si_signo, info->si_errno, info->si_code,
1143  describe (sig, info->si_code)));
1144 
1145  // These are set if the signal was sent by kill, POSIX signal
1146  // send or SIGCHLD.
1147  MYWRITE (fd, buf, snprintf (buf, buf_size, " pid = %ld, uid = %ld\n",
1148  (long) info->si_pid, (long) info->si_uid));
1149 
1150  // Child status for SIGCHLD.
1151  if (sig == SIGCHLD) {
1152  // Create temporary variables, as MacOS/clang doesn't want to
1153  // accept the on-the-fly conversion of the following variables
1154  // without printing some warnings.
1155  const long status = info->si_status;
1156  const long utime = info->si_utime;
1157  const long stime = info->si_stime;
1158  MYWRITE (fd, buf, snprintf (buf, buf_size,
1159  " status = %ld, utime = %ld, stime = %ld\n",
1160  status, utime, stime));
1161  }
1162 
1163  // These are set if the POSIX signal sender passed them.
1164  MYWRITE (fd, buf, snprintf (buf, buf_size, " value = (%d, %p)\n",
1165  info->si_int, info->si_ptr));
1166 
1167  // This is the interesting address for memory faults.
1168  if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS)
1169  MYWRITE (fd, buf, snprintf (buf, buf_size, " addr = %p\n", info->si_addr));
1170 
1171 # ifdef SIGPOLL // not darwin
1172  // SIGPOLL status data.
1173  if (sig == SIGPOLL)
1174  MYWRITE (fd, buf, snprintf (buf, buf_size, " band = %ld, fd = %d\n",
1175  (long) info->si_band, info->si_fd));
1176 # endif
1177 #endif // HAVE_POSIX_SIGNALS
1178 }
1179 
1184 void
1185 Signal::dumpMemory (IOFD fd, char *buf, unsigned int buf_size, const void *data, size_t n)
1186 {
1187  for (size_t i = 0; i < n; )
1188  {
1189  size_t m = snprintf (buf, buf_size, "\n ");
1190  for (size_t j = 0; i < n && j < 32; ++j, ++i)
1191  m += snprintf (buf + m, buf_size-m, "%s%02x",
1192  j % 4 == 0 ? " " : "",
1193  (unsigned int) (((const unsigned char *) data) [i]));
1194 
1195  MYWRITE (fd, buf, m);
1196  }
1197 }
1198 
1205 unsigned long
1206 Signal::dumpContext (IOFD fd, char *buf, unsigned int buf_size, const void *context)
1207 {
1208  unsigned long sp = 0;
1209 #if defined _WIN32 && defined _M_IX86
1210  const CONTEXT *uc = static_cast<const CONTEXT *> (context);
1211  sp = uc->Esp;
1212  MYWRITE (fd, buf, snprintf (buf, buf_size, "\n"
1213  "\n eip: %04lx:%08lx eflags: %08lx"
1214  "\n eax: %08lx ebx: %08lx"
1215  " ecx: %08lx edx: %08lx"
1216  "\n esi: %08lx edi: %08lx"
1217  " ebp: %08lx esp: %08lx"
1218  "\n ds: %04lx es: %04lx"
1219  " fs: %04lx ss: %04lx",
1220  uc->SegCs, uc->Eip, uc->EFlags,
1221  uc->Eax, uc->Ebx, uc->Ecx, uc->Edx,
1222  uc->Esi, uc->Edi, uc->Ebp, uc->Esp,
1223  uc->SegDs, uc->SegEs, uc->SegFs, uc->SegSs));
1224 
1225  MYWRITE (fd, buf, snprintf (buf, buf_size,
1226  "\n FPU: control = %08lx"
1227  "\n status = %08lx"
1228  "\n tag = %08lx"
1229  "\n ip = %04lx:%08lx"
1230  "\n data = %04lx:%08lx"
1231  "\n state = %08lx",
1232  uc->FloatSave.ControlWord,
1233  uc->FloatSave.StatusWord,
1234  uc->FloatSave.TagWord,
1235  uc->FloatSave.ErrorSelector,
1236  uc->FloatSave.ErrorOffset,
1237  uc->FloatSave.DataSelector,
1238  uc->FloatSave.DataOffset,
1239  uc->FloatSave.Cr0NpxState));
1240 
1241  for (int i = 0; i < 8; ++i)
1242  MYWRITE (fd, buf, snprintf (buf, buf_size.
1243  "\n %%fp%d = [%02x%02x:%02x%02x%02x%02x"
1244  "%02x%02x%02x%02x]",
1245  i,
1246  uc->FloatSave.RegisterArea [i * 10 + 0],
1247  uc->FloatSave.RegisterArea [i * 10 + 1],
1248  uc->FloatSave.RegisterArea [i * 10 + 2],
1249  uc->FloatSave.RegisterArea [i * 10 + 3],
1250  uc->FloatSave.RegisterArea [i * 10 + 4],
1251  uc->FloatSave.RegisterArea [i * 10 + 5],
1252  uc->FloatSave.RegisterArea [i * 10 + 6],
1253  uc->FloatSave.RegisterArea [i * 10 + 7],
1254  uc->FloatSave.RegisterArea [i * 10 + 8],
1255  uc->FloatSave.RegisterArea [i * 10 + 9]));
1256  MYWRITE (fd, "\n", 1);
1257 
1258 #elif HAVE_POSIX_SIGNALS
1259  // FIXME: how much of this is defined in POSIX or ABIs?
1260  const ucontext_t *uc = static_cast<const ucontext_t *> (context);
1261  const mcontext_t *mc = &uc->uc_mcontext;
1262  MYWRITE (fd, buf, snprintf (buf, buf_size, " stack = (%x, %x, %p)",
1263  uc->uc_stack.ss_flags,
1264  unsigned(uc->uc_stack.ss_size),
1265  uc->uc_stack.ss_sp));
1266 
1267  MYWRITE (fd, "\n", 1);
1268 #if defined __i386 && defined __linux
1269 # if !defined REG_CS && defined CS
1270 # define REG_CS CS
1271 # define REG_DS DS
1272 # define REG_ES ES
1273 # define REG_FS FS
1274 # define REG_SS SS
1275 # define REG_EIP EIP
1276 # define REG_EFL EFL
1277 # define REG_EAX EAX
1278 # define REG_EBX EBX
1279 # define REG_ECX ECX
1280 # define REG_EDX EDX
1281 # define REG_ESI ESI
1282 # define REG_EDI EDI
1283 # define REG_EBP EBP
1284 # define REG_ESP ESP
1285 # define REG_UESP UESP
1286 # define REG_TRAPNO TRAPNO
1287 # define REG_ERR ERR
1288 # endif
1289  sp = mc->gregs[REG_ESP];
1290  MYWRITE (fd, buf, snprintf (buf, buf_size,
1291  "\n eip: %04x:%08x eflags: %08x"
1292  "\n eax: %08x ebx: %08x"
1293  " ecx: %08x edx: %08x"
1294  "\n esi: %08x edi: %08x"
1295  " ebp: %08x esp: %08x"
1296  "\n ds: %04x es: %04x"
1297  " fs: %04x ss: %04x",
1298  mc->gregs [REG_CS] & 0xffff, mc->gregs [REG_EIP],
1299  mc->gregs [REG_EFL],
1300  mc->gregs [REG_EAX], mc->gregs [REG_EBX],
1301  mc->gregs [REG_ECX], mc->gregs [REG_EDX],
1302  mc->gregs [REG_ESI], mc->gregs [REG_EDI],
1303  mc->gregs [REG_EBP], mc->gregs [REG_ESP],
1304  mc->gregs [REG_DS] & 0xffff,
1305  mc->gregs [REG_ES] & 0xffff,
1306  mc->gregs [REG_FS] & 0xffff,
1307  mc->gregs [REG_SS] & 0xffff));
1308 
1309  MYWRITE (fd, buf, snprintf (buf, buf__size,
1310  "\n\n signal esp: %08x"
1311  " trap: %d/%d"
1312  " oldmask: %08lx cr2: %08lx",
1313  mc->gregs [REG_UESP],
1314  mc->gregs [REG_TRAPNO], mc->gregs [REG_ERR],
1315  mc->oldmask, mc->cr2));
1316 
1317  if (mc->fpregs)
1318  {
1319  MYWRITE (fd, buf, snprintf (buf, buf_size,
1320  "\n"
1321  "\n FPU: control = %08lx"
1322  "\n status = %08lx"
1323  "\n tag = %08lx"
1324  "\n ip = %04lx:%08lx"
1325  "\n data = %04lx:%08lx"
1326  "\n state = %08lx",
1327  mc->fpregs->cw, mc->fpregs->sw, mc->fpregs->tag,
1328  mc->fpregs->cssel & 0xffff, mc->fpregs->ipoff,
1329  mc->fpregs->datasel & 0xffff, mc->fpregs->dataoff,
1330  mc->fpregs->status));
1331 
1332  for (int i = 0; i < 8; ++i)
1333  MYWRITE (fd, buf, snprintf (buf, buf_size,
1334  "\n %%fp%d = [%04hx:%04hx%04hx%04hx%04hx]",
1335  i,
1336  mc->fpregs->_st [i].exponent,
1337  mc->fpregs->_st [i].significand [0],
1338  mc->fpregs->_st [i].significand [1],
1339  mc->fpregs->_st [i].significand [2],
1340  mc->fpregs->_st [i].significand [3]));
1341  }
1342 
1343 #elif defined __x86_64__ && defined __linux
1344  sp = mc->gregs[REG_RSP];
1345  MYWRITE (fd, buf, snprintf (buf, buf_size,
1346  "\n rip: %04x:%016llx eflags: %016llx"
1347  "\n rax: %016llx rbx: %016llx"
1348  "\n rcx: %016llx rdx: %016llx"
1349  "\n r08: %016llx r09: %016llx"
1350  "\n r10: %016llx r11: %016llx"
1351  "\n r12: %016llx r13: %016llx"
1352  "\n r14: %016llx r15: %016llx"
1353  "\n rsi: %016llx rdi: %016llx"
1354  "\n rbp: %016llx rsp: %016llx"
1355  "\n gs: %04x fs: %04x",
1356  (unsigned)mc->gregs [REG_CSGSFS] & 0xffff,
1357  (unsigned long long)mc->gregs [REG_RIP],
1358  (unsigned long long)mc->gregs [REG_EFL],
1359  (unsigned long long)mc->gregs [REG_RAX],
1360  (unsigned long long)mc->gregs [REG_RBX],
1361  (unsigned long long)mc->gregs [REG_RCX],
1362  (unsigned long long)mc->gregs [REG_RDX],
1363  (unsigned long long)mc->gregs [REG_R8],
1364  (unsigned long long)mc->gregs [REG_R9],
1365  (unsigned long long)mc->gregs [REG_R10],
1366  (unsigned long long)mc->gregs [REG_R11],
1367  (unsigned long long)mc->gregs [REG_R12],
1368  (unsigned long long)mc->gregs [REG_R13],
1369  (unsigned long long)mc->gregs [REG_R14],
1370  (unsigned long long)mc->gregs [REG_R15],
1371  (unsigned long long)mc->gregs [REG_RSI],
1372  (unsigned long long)mc->gregs [REG_RDI],
1373  (unsigned long long)mc->gregs [REG_RBP],
1374  (unsigned long long)mc->gregs [REG_RSP],
1375  (unsigned)(mc->gregs [REG_CSGSFS]>>16) & 0xffff,
1376  (unsigned)(mc->gregs [REG_CSGSFS]>>32) & 0xffff));
1377 
1378  MYWRITE (fd, buf, snprintf (buf, buf_size,
1379  "\n\n"
1380  " trap: %llu/%llu"
1381  " oldmask: %16llx cr2: %016llx",
1382  (unsigned long long)mc->gregs [REG_TRAPNO],
1383  (unsigned long long)mc->gregs [REG_ERR],
1384  (unsigned long long)mc->gregs [REG_OLDMASK],
1385  (unsigned long long)mc->gregs [REG_CR2]));
1386 
1387  if (mc->fpregs)
1388  {
1389  MYWRITE (fd, buf, snprintf (buf, buf_size,
1390  "\n"
1391  "\n FPU: control = %04x"
1392  "\n status = %04x"
1393  "\n tag = %02x"
1394  "\n op = %04x"
1395  "\n ip = %016lx"
1396  "\n data = %016lx"
1397  "\n mxcsr = %08x"
1398  "\n mxcr_mask= %08x",
1399  mc->fpregs->cwd,
1400  mc->fpregs->swd,
1401  mc->fpregs->ftw,
1402  mc->fpregs->fop,
1403  mc->fpregs->rip,
1404  mc->fpregs->rdp,
1405  mc->fpregs->mxcsr,
1406  mc->fpregs->mxcr_mask));
1407 
1408  for (int i = 0; i < 8; ++i)
1409  MYWRITE (fd, buf, snprintf (buf, buf_size,
1410  "\n %%fp%d = [%04hx:%04hx%04hx%04hx%04hx]",
1411  i,
1412  mc->fpregs->_st [i].exponent,
1413  mc->fpregs->_st [i].significand [0],
1414  mc->fpregs->_st [i].significand [1],
1415  mc->fpregs->_st [i].significand [2],
1416  mc->fpregs->_st [i].significand [3]));
1417 
1418  for (int i = 0; i < 16; ++i)
1419  MYWRITE (fd, buf, snprintf (buf, buf_size,
1420  "\n %%xmm%02d = [%08x %08x %08x %08x]",
1421  i,
1422  mc->fpregs->_xmm[i].element[0],
1423  mc->fpregs->_xmm[i].element[1],
1424  mc->fpregs->_xmm[i].element[2],
1425  mc->fpregs->_xmm[i].element[3]));
1426  }
1427 
1428 #elif __APPLE__ && defined __ppc__
1429  MYWRITE (fd, buf, snprintf (buf, buf_size, "\n dar: %08lx dsisr: %08lx exception: %08lx",
1430  (*mc)->es.dar, (*mc)->es.dsisr, (*mc)->es.exception));
1431 
1432  MYWRITE (fd, buf, snprintf (buf, buf_size,
1433  "\n srr0: %08x srr1: %08x cr: %08x xer: %08x"
1434  "\n lr: %08x ctr: %08x vrsave: %08x fpscr: %08x",
1435  (*mc)->ss.srr0, (*mc)->ss.srr1, (*mc)->ss.cr, (*mc)->ss.xer,
1436  (*mc)->ss.lr, (*mc)->ss.ctr, (*mc)->ss.vrsave, (*mc)->fs.fpscr));
1437 
1438  MYWRITE (fd, buf, snprintf (buf, buf_size, "\n vrvalid: %08x vscr: %08lx:%08lx:%08lx:%08lx\n",
1439  (*mc)->vs.save_vrvalid,
1440  (*mc)->vs.save_vscr [0], (*mc)->vs.save_vscr [1],
1441  (*mc)->vs.save_vscr [2], (*mc)->vs.save_vscr [3]));
1442 
1443  for (unsigned int *regs = &(*mc)->ss.r0, i = 0; i < 32; i += 4)
1444  MYWRITE (fd, buf, snprintf (buf, buf_size, "\n r%-2d %08x r%-2d %08x r%-2d %08x r%-2d %08x",
1445  i, regs [i], i+1, regs [i+1], i+2, regs [i+2], i+3, regs [i+3]));
1446  for (int i = 0; i < 32; ++i)
1447  MYWRITE (fd, buf, snprintf (buf, buf_size, "\n fp%-2d %016qx (%f)", i,
1448  *(unsigned long long *) &(*mc)->fs.fpregs [i],
1449  (*mc)->fs.fpregs [i]));
1450  for (int i = 0; i < 32; ++i)
1451  MYWRITE (fd, buf, snprintf (buf, buf_size, "\n vr%-2d %08lx:%08lx:%08lx:%08lx", i,
1452  (*mc)->vs.save_vr[i][0], (*mc)->vs.save_vr[i][1],
1453  (*mc)->vs.save_vr[i][2], (*mc)->vs.save_vr[i][3]));
1454 #elif defined __aarch64__ && defined __linux
1455  CxxUtils::aarch64_dump_registers (fd, buf, buf_size, *mc);
1456 #elif __sun
1457  for (int i = 0; i < NGREG; i++)
1458  MYWRITE (fd, buf, snprintf (buf, buf_size, "%s %%r%02d = %08x",
1459  i % 4 == 0 ? "\n" : "", i, mc->gregs [i]));
1460 #else
1461  dumpMemory (fd, buf, buf_size, mc, sizeof (*mc));
1462 #endif // __i386 && __linux, __sun, other
1463 
1464  MYWRITE (fd, "\n", 1);
1465 #endif // HAVE_POSIX_SIGNALS
1466 
1467  return sp;
1468 }
1469 
1508 static char buf[SIGNAL_MESSAGE_BUFSIZE];
1509 bool
1510 Signal::fatalDump ATLAS_NOT_THREAD_SAFE (int sig, siginfo_t *info, void *extra)
1511 {
1512  return fatalDump (sig, info, extra, s_fatalFd, s_fatalOptions);
1513 }
1514 bool
1515 Signal::fatalDump ATLAS_NOT_THREAD_SAFE (int sig, siginfo_t *info, void *extra,
1516  IOFD fd,
1517  unsigned options)
1518 {
1519  const unsigned int buf_size = sizeof (buf);
1520  bool haveCore = false;
1521  if (sig < 0)
1522  {
1523  sig = -sig;
1524  haveCore = true;
1525  }
1526 
1527  if (options & FATAL_DUMP_SIG)
1528  {
1529  MYWRITE (fd, "\n", 1);
1530  if (s_applicationName)
1531  {
1532  MYWRITE (fd, s_applicationName,
1533  STDC::strlen (s_applicationName));
1534  MYWRITE (fd, " ", 1);
1535  }
1536 
1537  MYWRITE (fd, buf,
1538  snprintf (buf, SIGNAL_MESSAGE_BUFSIZE, "(pid=%ld ppid=%ld) received fatal signal %d"
1539  " (%.100s)%s\n",
1540  (long) ProcessInfo__pid (), (long) ProcessInfo__ppid (), // wlav :: -> __ (x2)
1541  sig, name (sig), haveCore ? " (core dumped)" : ""));
1542 
1543  MYWRITE (fd, buf, snprintf(buf, buf_size, "signal context:\n"));
1544  dumpInfo (fd, buf, buf_size, sig, info);
1545  }
1546 
1547  unsigned long sp = 0;
1548  if (options & FATAL_DUMP_CONTEXT)
1549  sp = dumpContext (fd, buf, buf_size, extra);
1550 
1551  if (options & FATAL_DUMP_STACK)
1552  {
1553  MYWRITE (fd, buf, snprintf(buf, buf_size, "\nstack trace:\n"));
1554  if (s_lastSP) {
1555  MYWRITE (fd, buf, snprintf(buf, buf_size, "\n(backtrace failed; raw dump follows)\n"));
1556  MYWRITE (fd, buf, snprintf(buf, buf_size, "%016lx:", s_lastSP.load()));
1557  dumpMemory (fd, buf, buf_size, reinterpret_cast<void*>(s_lastSP.load()), 1024);
1558  MYWRITE (fd, buf, snprintf(buf, buf_size, "\n\n"));
1559  }
1560  else {
1561  s_lastSP = sp;
1562  DebugAids::stacktrace (fd);
1563  }
1564  s_lastSP = 0;
1565  }
1566 
1567  if (options & FATAL_DUMP_LIBS)
1568  {
1569  MYWRITE (fd, buf, snprintf(buf, buf_size, "\nshared libraries present:\n"));
1570  try { SharedLibrary::loaded (*SignalDumpCallback); }
1571  catch (...) { ; }
1572  }
1573 
1574  return true;
1575 }
1576 
1579 IOFD
1580 Signal::handleFatalFd ATLAS_NOT_THREAD_SAFE (void)
1581 {
1582  // Automatically initialise on first access.
1583  if (s_fatalFd == IOFD_INVALID)
1584  s_fatalFd = STDERR_HANDLE;
1585 
1586  return s_fatalFd;
1587 }
1588 
1592 Signal::handleFatalHook ATLAS_NOT_THREAD_SAFE (void)
1593 { return s_fatalHook; }
1594 
1598 Signal::handleFatalReturn ATLAS_NOT_THREAD_SAFE (void)
1599 { return s_fatalReturn; }
1600 
1603 unsigned
1604 Signal::handleFatalOptions ATLAS_NOT_THREAD_SAFE (void)
1605 { return s_fatalOptions; }
1606 
1610 Signal::handleQuitHook ATLAS_NOT_THREAD_SAFE (void)
1611 { return s_quitHook; }
1612 
1621 int
1622 Signal::fatalLevel ATLAS_NOT_THREAD_SAFE (void)
1623 { return s_inFatal; }
1624 
1628 bool
1629 Signal::crashed ATLAS_NOT_THREAD_SAFE (void)
1630 { return s_crashed; }
1631 
1632 //} // namespace seal wlav
1633 } // namespace Athena wlav
1634 
1635 
1636 extern "C" {
1639  void CxxUtils_installFatalHandler ATLAS_NOT_THREAD_SAFE ()
1640  {
1641  Athena::Signal::handleFatal(nullptr, 1);
1642  }
1643 }
grepfile.info
info
Definition: grepfile.py:38
pid_t
int32_t pid_t
Definition: FPGATrackSimTypes.h:19
Athena::Signal::raise
static int raise(int sig)
Raise the signal number sig.
Definition: SealSignal.cxx:377
Athena::Signal::s_applicationName
static const char * s_applicationName
The current application name.
Definition: SealSignal.h:276
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
Athena::Signal::s_fatalFd
static IOFD s_fatalFd
The output file descriptor for #fataldump().
Definition: SealSignal.h:277
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
Athena::Signal::suspend
static void suspend(const sigset_t *mask)
Temporarily replace the signal mask of the process with mask and then suspend until a signal is recei...
Definition: SealSignal.cxx:500
siginfo_t
Definition: SealSignal.h:77
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
Athena::Signal::s_crashed
static bool s_crashed
Indicator that the application has been crashed: that a fatal signal has been delivered.
Definition: SealSignal.h:273
arm_helpers.h
Athena::DebugAids::coredump
static void coredump(int sig,...)
Drop a core dump and continue.
Definition: SealDebug.cxx:971
Athena::Signal::s_fatalOptions
static unsigned s_fatalOptions
The current fatal signal handling options.
Definition: SealSignal.h:280
SealDebug.h
This are the SEAL debug aids, adapted to build in Atlas, after the drop of that project.
Athena::SharedLibrary::InfoHandler
Callback1< const LibraryInfo & > InfoHandler
Definition: SealSharedLib.h:175
SealCommon.h
Collecting a few shared bits and pieces from SEAL headers.
athena.value
value
Definition: athena.py:124
Athena::Signal::dumpMemory
static void dumpMemory(IOFD fd, char *buf, unsigned int buf_size, const void *data, size_t n)
Utility function to dump memory section from data for n bytes.
Definition: SealSignal.cxx:1185
Athena::Signal::dumpContext
static unsigned long dumpContext(IOFD fd, char *buf, unsigned int buf_size, const void *context)
Utility function to dump the process context, as obtained for instance through signal handler paramet...
Definition: SealSignal.cxx:1206
Athena::BitTraits::HexDigits
@ HexDigits
Definition: SealDebug.h:67
stime
std::string stime()
return the current data and time
Definition: computils.cxx:214
Athena::Signal::handler
static HandlerType handler(int sig, sigset_t *mask=0)
Return the current handler for signal number sig and its blocked signals in mask (if non-null).
Definition: SealSignal.cxx:236
x
#define x
SUSY_SimplifiedModel_PostInclude.process
string process
Definition: SUSY_SimplifiedModel_PostInclude.py:42
python.utils.AtlRunQueryLookup.mask
string mask
Definition: AtlRunQueryLookup.py:460
sigaddset
#define sigaddset(x, y)
Definition: SealSignal.h:84
handler
void handler(int sig)
signal handler
Definition: rmain.cxx:98
sigset_t
int sigset_t
Definition: SealSignal.h:80
Cut::signal
@ signal
Definition: SUSYToolsAlg.cxx:67
histSizes.code
code
Definition: histSizes.py:129
mc
Definition: mc.PG_single_nu_valid.py:1
SealSharedLib.h
CaloCondBlobAlgs_fillNoiseFromASCII.desc
desc
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:54
InDetDD::PixelDiodeType::LONG
@ LONG
Athena::Signal::mask
static void mask(const sigset_t *mask, sigset_t *old=0)
Set the list of currently blocked signals to mask and return the old setting in old (if non-null).
Definition: SealSignal.cxx:365
lumiFormat.i
int i
Definition: lumiFormat.py:85
sigismember
#define sigismember(x, y)
Definition: SealSignal.h:86
SealSignal.h
This is the signal handler from SEAL, adapted to build in Atlas, after the drop of that project.
Athena
Some weak symbol referencing magic...
Definition: AthLegacySequence.h:21
Athena::Signal::wait
static bool wait(int sig, siginfo_t *info=0, long msecs=-1)
Suspend the thread waiting for signal sig at most msecs milliseconds.
Definition: SealSignal.cxx:515
beamspotman.n
n
Definition: beamspotman.py:731
Athena::Signal::ignore
static void ignore(int sig)
Ignore the signal number sig.
Definition: SealSignal.cxx:331
IOFD
int IOFD
Type the system uses for channel descriptors.
Definition: SealCommon.h:27
Athena::Signal::s_quitHook
static QuitHook s_quitHook
The application handler hook for quitting-related signals.
Definition: SealSignal.h:281
Athena::Signal::FatalReturn
void(* FatalReturn)(int sig, siginfo_t *info, void *x)
Application hook to jump back to the main program from a fatal signal, for example using #siglongjmp.
Definition: SealSignal.h:182
python.BuildSignatureFlags.sig
sig
Definition: BuildSignatureFlags.py:218
Athena::Signal::HandlerType
void(* HandlerType)(int sig, siginfo_t *info, void *extra)
Signal handler type.
Definition: SealSignal.h:196
Athena::Signal::queue
static int queue(int sig, int value=0)
Queue signal sig for this process with additional data value.
Definition: SealSignal.cxx:446
python.AtlRunQueryLib.options
options
Definition: AtlRunQueryLib.py:379
beamspotman.stat
stat
Definition: beamspotman.py:266
Athena::Signal::name
static const char * name(int sig)
Return the name of the signal number sig.
Definition: SealSignal.cxx:216
python.handimod.extra
int extra
Definition: handimod.py:522
ReadFromCoolCompare.fd
fd
Definition: ReadFromCoolCompare.py:196
Athena::Signal::s_lastSP
static std::atomic< unsigned long > s_lastSP
Used to switch to a raw stack dump if we crash during a backtrace.
Definition: SealSignal.h:275
Athena::BitTraits
Describe the bit features of an integral type T.
Definition: SealDebug.h:55
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
IOFD_INVALID
#define IOFD_INVALID
Invalid channel descriptor constant.
Definition: SealCommon.h:20
Athena::Signal::trampoline
static void trampoline(int sig)
Internal signal handler trampoline to convert handler arguments to look more like POSIX signals.
Definition: SealSignal.cxx:203
Athena::Signal::s_fatalHook
static FatalHook s_fatalHook
The application handler hook for fatal signals.
Definition: SealSignal.h:278
Athena::Signal::block
static void block(int sig, bool sense)
Block or unblock the signal number sig.
Definition: SealSignal.cxx:338
Athena::Signal::describe
static const char * describe(int sig, int code)
Return the description for signal info code code for signal number sig.
Definition: SealSignal.cxx:968
Athena::Signal::FatalHook
bool(* FatalHook)(int sig, siginfo_t *info, void *x)
Application hook to run in fatal().
Definition: SealSignal.h:176
python.PyAthena.v
v
Definition: PyAthena.py:154
Athena::Signal::s_fatalReturn
static FatalReturn s_fatalReturn
The application main return hook for fatal signals.
Definition: SealSignal.h:279
CSV_InDetExporter.old
old
Definition: CSV_InDetExporter.py:145
Athena::Signal::handle
static HandlerType handle(int sig, HandlerType handler, const sigset_t *blockMask=0)
Install a new signal handler handler for signal number sig and returns the old handler.
Definition: SealSignal.cxx:277
Athena::SharedLibrary::loaded
static void loaded(InfoHandler &handler)
Iterate and provide information about all currently loaded shared libraries.
Definition: SealSharedLib.cxx:290
Athena::Signal::dumpInfo
static void dumpInfo(IOFD fd, char *buf, unsigned int buf_size, int sig, const siginfo_t *info)
Utility function to dump the signal info descriptor for signal sig, as obtained for instance through ...
Definition: SealSignal.cxx:1084
merge.status
status
Definition: merge.py:17
Athena::Signal::QuitHook
bool(* QuitHook)(int sig, siginfo_t *info, void *x)
Application clean-up hook invoked before #quit(int , siginfo_t *, void *) exits from program terminat...
Definition: SealSignal.h:165
ATLAS_NOT_THREAD_SAFE
void CxxUtils_installFatalHandler ATLAS_NOT_THREAD_SAFE()
Install fatal handler with default options.
Definition: SealSignal.cxx:1639
python.CaloScaleNoiseConfig.ts
ts
Definition: CaloScaleNoiseConfig.py:86
Athena::Signal::revert
static void revert(int sig)
Revert the signal number sig back to its default behaviour.
Definition: SealSignal.cxx:326
Athena::Signal::s_inFatal
static int s_inFatal
Indicator that we are currently executing inside #fatal().
Definition: SealSignal.h:274
Athena::Signal::kill
static int kill(pid_t process, int sig)
Send the signal sig to process identified by process.
Definition: SealSignal.cxx:389
Athena::ATLAS_NOT_THREAD_SAFE
void DebugAids::stacktraceLine ATLAS_NOT_THREAD_SAFE(IOFD fd, unsigned long addr)
Write out stack trace line to FD.
Definition: SealDebug.cxx:328
Athena::Signal::pending
static bool pending(int sig)
Check if sig is pending for this process.
Definition: SealSignal.cxx:471
Athena::Signal::s_trampolines
static HandlerType s_trampolines[NSIG]
Actual signal handlers when POSIX signals are not available.
Definition: SealSignal.h:283
Athena::CreateCallback
Callback1Rep< T1 > * CreateCallback(void(*function)(T1, T2), const T2 &fill_2)
Definition: SealSharedLib.h:136
sigemptyset
#define sigemptyset(x)
Definition: SealSignal.h:82
STDERR_HANDLE
#define STDERR_HANDLE
Definition: SealDebug.h:34
Athena::DummyHandlerType
void(* DummyHandlerType)(int)
Dummy handler type for standard signal() function.
Definition: SealSignal.cxx:109
MYWRITE
#define MYWRITE(fd, data, n)
Definition: SealDebug.h:44