diff --git a/core/unix/src/TUnixSignalManager.cxx b/core/unix/src/TUnixSignalManager.cxx index 3084755e9e253..7eafbf1b09062 100644 --- a/core/unix/src/TUnixSignalManager.cxx +++ b/core/unix/src/TUnixSignalManager.cxx @@ -97,6 +97,17 @@ class TFdSet; +static const int kStringLength = 255; + +struct StackTraceHelper_t { + char fShellExec[kStringLength]; + char fPidString[kStringLength]; + char fPidNum[kStringLength]; + int fParentToChild[2]; + int fChildToParent[2]; + std::unique_ptr fHelperThread; +}; + #if defined(HAVE_DLADDR) && !defined(R__MACOSX) //////////////////////////////////////////////////////////////////////////////// @@ -222,23 +233,7 @@ static int SignalSafeErrWrite(const char *text) { //---- helper ----------------------------------------------------------------- -static const int kStringLength = 255; - -static struct StackTraceHelper_t { - char fShellExec[kStringLength]; - char fPidString[kStringLength]; - char fPidNum[kStringLength]; - int fParentToChild[2]; - int fChildToParent[2]; - std::unique_ptr fHelperThread; -} gStackTraceHelper = { // the order of the signals should be identical - { }, - { }, - { }, - {-1,-1}, - {-1,-1}, - nullptr -}; +static StackTraceHelper_t gStackTraceHelper; static char * const kStackArgv[] = {gStackTraceHelper.fShellExec, gStackTraceHelper.fPidString, gStackTraceHelper.fPidNum, nullptr}; @@ -272,6 +267,13 @@ void TUnixSignalManager::Init() fSignals = new TFdSet; + //--- initialize pipe-related data structer here, macosx does not recognize their values if they were inialized after UnixSignal functions + gStackTraceHelper.fParentToChild[0] = -1; + gStackTraceHelper.fParentToChild[1] = -1; + gStackTraceHelper.fChildToParent[0] = -1; + gStackTraceHelper.fChildToParent[1] = -1; + gStackTraceHelper.fHelperThread = nullptr; + //--- install default handlers UnixSignal(kSigChild, SigHandler); UnixSignal(kSigBus, SigHandler); @@ -290,22 +292,25 @@ void TUnixSignalManager::Init() } #ifdef ROOTETCDIR +#if defined(R__MACOSX) + if(snprintf(gStackTraceHelper.fPidString, kStringLength-1, "%s/lldb-backtrace.sh", ROOTETCDIR) >= kStringLength) { +#else if(snprintf(gStackTraceHelper.fPidString, kStringLength-1, "%s/gdb-backtrace.sh", ROOTETCDIR) >= kStringLength) { +#endif SignalSafeErrWrite("Unable to pre-allocate executable information"); return; } +#else +#if defined(R__MACOSX) + if(snprintf(gStackTraceHelper.fPidString, kStringLength-1, "%s/etc/lldb-backtrace.sh", gSystem->Getenv("ROOTSYS")) >= kStringLength) { #else if(snprintf(gStackTraceHelper.fPidString, kStringLength-1, "%s/etc/gdb-backtrace.sh", gSystem->Getenv("ROOTSYS")) >= kStringLength) { +#endif SignalSafeErrWrite("Unable to pre-allocate executable information"); return; } #endif - gStackTraceHelper.fParentToChild[0] = -1; - gStackTraceHelper.fParentToChild[1] = -1; - gStackTraceHelper.fChildToParent[0] = -1; - gStackTraceHelper.fChildToParent[1] = -1; - StackTraceHelperInit(); } diff --git a/etc/lldb-backtrace.sh b/etc/lldb-backtrace.sh new file mode 100755 index 0000000000000..c4a60c50f9b3a --- /dev/null +++ b/etc/lldb-backtrace.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# This script is used by TUnixSystem::StackTrace() on MacOS X if lldb is supported. + +tempname=`basename $0 .sh` + +OUTFILE=/dev/stdout + +if [ `uname -s` != "Darwin" ]; then + + echo "lldb stacktrace is only supported on MacOSX." + exit 1 + +else + + if test $# -lt 1; then + echo "Usage: ${tempname} " 1>&2 + exit 1 + fi + + TMPFILE=`mktemp -q /tmp/${tempname}.XXXXXX` + if test $? -ne 0; then + echo "${tempname}: can't create temp file, exiting..." 1>&2 + exit 1 + fi + + backtrace="thread backtrace all" + + echo $backtrace > $TMPFILE + + LLDB=${LLDB:-lldb} + + # Run LLDB, strip out unwanted noise. + $LLDB -b -x -s $TMPFILE -p $1 2>&1 < /dev/null | + sed -n \ + -e '/[Tt]hread #[0-9]/p' \ + -e '/[Ff]rame #[0-9]/p' > $OUTFILE + + rm -f $TMPFILE + +fi