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