ATLAS Offline Software
Loading...
Searching...
No Matches
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
19
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
31static 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
73static pid_t
75{
76#ifdef _WIN32
77 return GetCurrentProcessId ();
78#else
79 return ::getpid ();
80#endif
81}
82
84static pid_t
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
103namespace Athena { // wlav
104//<<<<<< PRIVATE DEFINES >>>>>>
105//<<<<<< PRIVATE CONSTANTS >>>>>>
106//<<<<<< PRIVATE TYPES >>>>>>
107
109extern "C" { typedef void (*DummyHandlerType) (int); }
110
111//<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>>
112
119
120//<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>>
121//<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>>
122
125bool Signal::s_crashed = false;
126
129int 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.
136std::atomic<unsigned long> Signal::s_lastSP (0);
137
139const char *Signal::s_applicationName = 0;
140
143
146
149
151unsigned Signal::s_fatalOptions = 0;
152
155
156#if !HAVE_POSIX_SIGNALS || !SA_SIGINFO
164#endif
165
166//<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>>
167
174static void
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
187static LONG CALLBACK
188SEHFatal (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
202void
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
215const 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
236Signal::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);
254 signal (sig, (DummyHandlerType) old);
255 return old;
256#endif // HAVE_POSIX_SIGNALS
257}
258
277Signal::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 {
292 s_trampolines [sig] = handler;
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
319 (HandlerType) ::signal (sig, (DummyHandlerType) handler);
320#endif // HAVE_POSIX_SIGNALS
321 return oldhandler;
322}
323
325void
327{ handle (sig, (HandlerType) (void*)SIG_DFL); }
328
330void
332{ handle (sig, (HandlerType) (void*)SIG_IGN); }
333
337void
338Signal::block (int sig, bool sense)
339{
340#if HAVE_POSIX_SIGNALS
341 // FIXME: threads -- need to use pthread_sigmask
343 sigemptyset (&mask);
344 sigaddset (&mask, sig);
345 block (&mask, sense);
346#endif
347}
348
352void
353Signal::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
364void
365Signal::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
376int
378{
379#if HAVE_RAISE
380 return ::raise (sig);
381#else
382 return ::kill (getpid (), sig);
383#endif
384}
385
388int
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
402int
403Signal::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
410int
411Signal::queue (pid_t /*process*/, int /*sig*/, int /*value = 0 */)
412{
413 return 0;
414}
415#endif
416
419#if HAVE_POSIX_RT_SIGNALS
420int
421Signal::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
428int
429Signal::queue (pid_t /*process*/, int /*sig*/, void */*value*/)
430{
431 return 0;
432}
433#endif
434
438#if HAVE_POSIX_RT_SIGNALS
439int
440Signal::queue (int sig, int value /* = 0 */)
441{
442 return queue (getpid (), sig, value);
443}
444#else
445int
446Signal::queue (int /*sig*/, int /*value = 0 */)
447{
448 return 0;
449}
450#endif
451
455#if HAVE_POSIX_RT_SIGNALS
456int
457Signal::queue (int sig, void *value)
458{
459 return queue (getpid (), sig, value);
460}
461#else
462int
463Signal::queue (int /*sig*/, void */*value*/)
464{
465 return 0;
466}
467#endif
468
470bool
472{ sigset_t s; pending (&s); return sigismember (&s, sig); }
473
475#if HAVE_POSIX_SIGNALS
476void
478{
479 assert (mask);
480 sigpending (mask);
481}
482#else
483void
485{
486}
487#endif
488
491#if HAVE_POSIX_SIGNALS
492void
493Signal::suspend (const sigset_t *mask)
494{
495 assert (mask);
496 sigsuspend (mask);
497}
498#else
499void
500Signal::suspend (const sigset_t */*mask*/)
501{
502}
503#endif
504
514bool
515Signal::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
536int
537Signal::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
561int
562Signal::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. */
580void
581Signal::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
645void
646Signal::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;
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
816void
817Signal::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
894void
895Signal::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
967const char *
968Signal::describe (int sig, int code)
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
1083void
1084Signal::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
1184void
1185Signal::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
1205unsigned long
1206Signal::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
1509bool
1510Signal::fatalDump ATLAS_NOT_THREAD_SAFE (int sig, siginfo_t *info, void *extra)
1511{
1512 return fatalDump (sig, info, extra, s_fatalFd, s_fatalOptions);
1513}
1514bool
1515Signal::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"));
1571 catch (...) { ; }
1572 }
1573
1574 return true;
1575}
1576
1579IOFD
1580Signal::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
1592Signal::handleFatalHook ATLAS_NOT_THREAD_SAFE (void)
1593{ return s_fatalHook; }
1594
1598Signal::handleFatalReturn ATLAS_NOT_THREAD_SAFE (void)
1599{ return s_fatalReturn; }
1600
1603unsigned
1604Signal::handleFatalOptions ATLAS_NOT_THREAD_SAFE (void)
1605{ return s_fatalOptions; }
1606
1610Signal::handleQuitHook ATLAS_NOT_THREAD_SAFE (void)
1611{ return s_quitHook; }
1612
1621int
1622Signal::fatalLevel ATLAS_NOT_THREAD_SAFE (void)
1623{ return s_inFatal; }
1624
1628bool
1629Signal::crashed ATLAS_NOT_THREAD_SAFE (void)
1630{ return s_crashed; }
1631
1632//} // namespace seal wlav
1633} // namespace Athena wlav
1634
1635
1636extern "C" {
1639 void CxxUtils_installFatalHandler ATLAS_NOT_THREAD_SAFE ()
1640 {
1641 Athena::Signal::handleFatal(nullptr, 1);
1642 }
1643}
int32_t pid_t
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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)
Definition SealDebug.h:44
#define STDERR_HANDLE
Definition SealDebug.h:34
static pid_t ProcessInfo__pid(void)
Get the process id.
void CxxUtils_installFatalHandler ATLAS_NOT_THREAD_SAFE()
Install fatal handler with default options.
static const int SIGNAL_MESSAGE_BUFSIZE
Maximum length of a signal message.
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 void coredump(int sig,...)
Drop a core dump and continue.
static void loaded(InfoHandler &handler)
Iterate and provide information about all currently loaded shared libraries.
Callback1< const LibraryInfo & > InfoHandler
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
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....
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.
Callback1Rep< T1 > * CreateCallback(void(*function)(T1, T2), const T2 &fill_2)
Information about a currently loaded shared library.