From af454fe10212f16f73dc874b7807b50f1ca342de Mon Sep 17 00:00:00 2001 From: Zhe Zhang Date: Tue, 19 Jan 2016 19:57:18 -0600 Subject: [PATCH 1/7] Created a new class TSigHandling out of TSystem and TSigHandling is dedicated to handling signals of the system --- core/base/inc/LinkDef2.h | 1 + core/base/inc/TSigHandling.h | 94 ++++ core/base/inc/TSystem.h | 5 +- core/base/src/TROOT.cxx | 2 + core/base/src/TSigHandling.cxx | 162 +++++++ core/base/src/TSystem.cxx | 31 +- core/unix/CMakeLists.txt | 2 +- core/unix/inc/LinkDef.h | 1 + core/unix/inc/TUnixSigHandling.h | 73 +++ core/unix/inc/TUnixSystem.h | 8 +- core/unix/src/TUnixSigHandling.cxx | 756 +++++++++++++++++++++++++++++ core/unix/src/TUnixSystem.cxx | 343 +------------ 12 files changed, 1133 insertions(+), 345 deletions(-) create mode 100644 core/base/inc/TSigHandling.h create mode 100644 core/base/src/TSigHandling.cxx create mode 100644 core/unix/inc/TUnixSigHandling.h create mode 100644 core/unix/src/TUnixSigHandling.cxx diff --git a/core/base/inc/LinkDef2.h b/core/base/inc/LinkDef2.h index 44883b3c03f0f..07db22e4fb42b 100644 --- a/core/base/inc/LinkDef2.h +++ b/core/base/inc/LinkDef2.h @@ -131,6 +131,7 @@ #pragma link C++ class TStringToken; #pragma link C++ class TSubString; #pragma link C++ class TSysEvtHandler; +#pragma link C++ class TSigHandling+; #pragma link C++ class TSystem+; #pragma link C++ class TSystemFile+; #pragma link C++ class TSystemDirectory+; diff --git a/core/base/inc/TSigHandling.h b/core/base/inc/TSigHandling.h new file mode 100644 index 0000000000000..3a7bcdd5e52b8 --- /dev/null +++ b/core/base/inc/TSigHandling.h @@ -0,0 +1,94 @@ +// @(#)root/base:$Id$ +// Author: Fons Rademakers 15/09/95 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TSigHandling +#define ROOT_TSigHandling + + +////////////////////////////////////////////////////////////////////////// +// // +// TSigHandling // +// // +// Abstract base class defining a generic interface to the underlying // +// Operating System. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef __CINT__ +#include +#include +#include +#ifndef WIN32 +#include +#endif +#endif + +#ifndef ROOT_TNamed +#include "TNamed.h" +#endif +#ifndef ROOT_TString +#include "TString.h" +#endif +#ifndef ROOT_TInetAddress +#include "TInetAddress.h" +#endif +#ifndef ROOT_TTimer +#include "TTimer.h" +#endif +#ifndef ROOT_ThreadLocalStorage +#include "ThreadLocalStorage.h" +#endif + +class TSeqCollection; +class TFdSet; +class TVirtualMutex; + +#ifdef __CINT__ +typedef void *Func_t; +#else +typedef void ((*Func_t)()); +#endif + +R__EXTERN const char *gRootDir; +R__EXTERN TVirtualMutex *gSystemMutex; + +class TSigHandling : public TNamed { + +protected: + TFdSet *fSignals; //!Signals that were trapped + Int_t fSigcnt; //Number of pending signals + TSeqCollection *fSignalHandler; //List of signal handlers + +public: + TSigHandling(const char *name = "Generic", const char *title = "Generic Signal Handling"); + virtual ~TSigHandling(); + + //---- Misc + virtual void Init(); + virtual void StackTrace(); + + //---- Handling of system signals + virtual Bool_t HaveTrappedSignal(Bool_t pendingOnly); + virtual void AddSignalHandler(TSignalHandler *sh); + virtual TSignalHandler *RemoveSignalHandler(TSignalHandler *sh); + virtual void ResetSignal(ESignals sig, Bool_t reset = kTRUE); + virtual void ResetSignals(); + virtual void IgnoreSignal(ESignals sig, Bool_t ignore = kTRUE); + virtual void IgnoreInterrupt(Bool_t ignore = kTRUE); + virtual TSeqCollection *GetListOfSignalHandlers(); + virtual void SigAlarmInterruptsSyscalls(Bool_t) { } + + ClassDef(TSigHandling,0) +}; + +R__EXTERN TSigHandling *gSigHandling; + +#endif diff --git a/core/base/inc/TSystem.h b/core/base/inc/TSystem.h index c1b341084dcc1..30f3f74af27bf 100644 --- a/core/base/inc/TSystem.h +++ b/core/base/inc/TSystem.h @@ -268,11 +268,9 @@ class TSystem : public TNamed { TFdSet *fWritemask; //!Files that should be checked for write events TFdSet *fReadready; //!Files with reads waiting TFdSet *fWriteready; //!Files with writes waiting - TFdSet *fSignals; //!Signals that were trapped Int_t fNfd; //Number of fd's in masks Int_t fMaxrfd; //Largest fd in read mask Int_t fMaxwfd; //Largest fd in write mask - Int_t fSigcnt; //Number of pending signals TString fWdpath; //Working directory TString fHostname; //Hostname Bool_t fInsideNotify; //Used by DispatchTimers() @@ -284,7 +282,6 @@ class TSystem : public TNamed { Int_t fLevel; //Level of nested eventloops TSeqCollection *fTimers; //List of timers - TSeqCollection *fSignalHandler; //List of signal handlers TSeqCollection *fFileHandler; //List of file handlers TSeqCollection *fStdExceptionHandler; //List of std::exception handlers TSeqCollection *fOnExitList; //List of items to be cleaned-up on exit @@ -368,7 +365,7 @@ class TSystem : public TNamed { virtual void ResetSignals(); virtual void IgnoreSignal(ESignals sig, Bool_t ignore = kTRUE); virtual void IgnoreInterrupt(Bool_t ignore = kTRUE); - virtual TSeqCollection *GetListOfSignalHandlers() const { return fSignalHandler; } + virtual TSeqCollection *GetListOfSignalHandlers(); virtual void AddFileHandler(TFileHandler *fh); virtual TFileHandler *RemoveFileHandler(TFileHandler *fh); virtual TSeqCollection *GetListOfFileHandlers() const { return fFileHandler; } diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index f92c6b6169f70..793abb20afc1e 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -145,6 +145,7 @@ namespace std {} using namespace std; #include "TUrl.h" #else #include "TUnixSystem.h" +#include "TUnixSigHandling.h" #endif #elif defined(R__WIN32) #include "TWinNTSystem.h" @@ -1690,6 +1691,7 @@ void TROOT::InitSystem() gSystem = new TMacOSXSystem; #else gSystem = new TUnixSystem; + gSigHandling = new TUnixSigHandling; #endif #elif defined(R__WIN32) gSystem = new TWinNTSystem; diff --git a/core/base/src/TSigHandling.cxx b/core/base/src/TSigHandling.cxx new file mode 100644 index 0000000000000..e0ea1cafd09be --- /dev/null +++ b/core/base/src/TSigHandling.cxx @@ -0,0 +1,162 @@ +// @(#)root/base:$Id: 8944840ba34631ec28efc779647618db43c0eee5 $ +// Author: Fons Rademakers 15/09/95 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +/** \class TSystem + +Abstract base class defining a generic interface to the underlying +Operating System. +This is not an ABC in the strict sense of the (C++) word. For +every member function there is an implementation (often not more +than a call to AbstractMethod() which prints a warning saying +that the method should be overridden in a derived class), which +allows a simple partial implementation for new OS'es. +*/ + +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include + +#include "Riostream.h" +#include "TSystem.h" +#include "TSigHandling.h" +#include "TApplication.h" +#include "TException.h" +#include "TROOT.h" +#include "TClass.h" +#include "TClassTable.h" +#include "TEnv.h" +#include "TBrowser.h" +#include "TString.h" +#include "TOrdCollection.h" +#include "TInterpreter.h" +#include "TRegexp.h" +#include "TTimer.h" +#include "TObjString.h" +#include "TError.h" +#include "TPluginManager.h" +#include "TUrl.h" +#include "TVirtualMutex.h" +#include "compiledata.h" +#include "RConfigure.h" + +TSigHandling *gSigHandling = 0; + +ClassImp(TSigHandling) + +//////////////////////////////////////////////////////////////////////////////// +/// Create a new OS interface. + +TSigHandling::TSigHandling(const char *name, const char *title) : TNamed(name, title) +{ + fSignals = 0; + fSigcnt = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Delete the OS interface. + +TSigHandling::~TSigHandling() +{ + if (fSignalHandler) { + fSignalHandler->Delete(); + SafeDelete(fSignalHandler); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Init the OS interface. +void TSigHandling::Init() +{ + fSignalHandler = new TOrdCollection; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Add a signal handler to list of system signal handlers. Only adds +/// the handler if it is not already in the list of signal handlers. + +Bool_t TSigHandling::HaveTrappedSignal(Bool_t) +{ + AbstractMethod("HaveTrappedSignal"); + return kFALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Add a signal handler to list of system signal handlers. Only adds +/// the handler if it is not already in the list of signal handlers. + +void TSigHandling::AddSignalHandler(TSignalHandler *) +{ + AbstractMethod("AddSignalHandler"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Remove a signal handler from list of signal handlers. Returns +/// the handler or 0 if the handler was not in the list of signal handlers. + +TSignalHandler *TSigHandling::RemoveSignalHandler(TSignalHandler *) +{ + AbstractMethod("RemoveSignalHandler"); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// If reset is true reset the signal handler for the specified signal +/// to the default handler, else restore previous behaviour. + +void TSigHandling::ResetSignal(ESignals /*sig*/, Bool_t /*reset*/) +{ + AbstractMethod("ResetSignal"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Reset signals handlers to previous behaviour. + +void TSigHandling::ResetSignals() +{ + AbstractMethod("ResetSignals"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// If ignore is true ignore the specified signal, else restore previous +/// behaviour. + +void TSigHandling::IgnoreSignal(ESignals /*sig*/, Bool_t /*ignore*/) +{ + AbstractMethod("IgnoreSignal"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// If ignore is true ignore the interrupt signal, else restore previous +/// behaviour. Typically call ignore interrupt before writing to disk. + +void TSigHandling::IgnoreInterrupt(Bool_t ignore) +{ + IgnoreSignal(kSigInterrupt, ignore); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Obtain the current signal handlers +TSeqCollection *TSigHandling::GetListOfSignalHandlers() +{ + return fSignalHandler; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Print a stack trace. + +void TSigHandling::StackTrace() +{ + AbstractMethod("StackTrace"); +} diff --git a/core/base/src/TSystem.cxx b/core/base/src/TSystem.cxx index c1c29ca1a563f..0ba18e6025d3e 100644 --- a/core/base/src/TSystem.cxx +++ b/core/base/src/TSystem.cxx @@ -48,6 +48,7 @@ allows a simple partial implementation for new OS'es. #include "TPluginManager.h" #include "TUrl.h" #include "TVirtualMutex.h" +#include "TSigHandling.h" #include "compiledata.h" #include "RConfigure.h" @@ -108,7 +109,6 @@ TSystem::TSystem(const char *name, const char *title) : TNamed(name, title), fAc Error("TSystem", "only one instance of TSystem allowed"); fOnExitList = 0; - fSignalHandler = 0; fFileHandler = 0; fStdExceptionHandler = 0; fTimers = 0; @@ -121,7 +121,6 @@ TSystem::TSystem(const char *name, const char *title) : TNamed(name, title), fAc fWritemask = 0; fReadready = 0; fWriteready = 0; - fSignals = 0; fDone = kFALSE; fAclicMode = kDefault; fInControl = kFALSE; @@ -129,12 +128,12 @@ TSystem::TSystem(const char *name, const char *title) : TNamed(name, title), fAc fMaxrfd = -1; fMaxwfd = -1; fNfd = 0; - fSigcnt = 0; if (!gLibraryVersion) { gLibraryVersion = new Int_t [gLibraryVersionMax]; memset(gLibraryVersion, 0, gLibraryVersionMax*sizeof(Int_t)); } + } //////////////////////////////////////////////////////////////////////////////// @@ -147,11 +146,6 @@ TSystem::~TSystem() SafeDelete(fOnExitList); } - if (fSignalHandler) { - fSignalHandler->Delete(); - SafeDelete(fSignalHandler); - } - if (fFileHandler) { fFileHandler->Delete(); SafeDelete(fFileHandler); @@ -190,10 +184,8 @@ Bool_t TSystem::Init() fMaxrfd = -1; fMaxwfd = -1; - fSigcnt = 0; fLevel = 0; - fSignalHandler = new TOrdCollection; fFileHandler = new TOrdCollection; fStdExceptionHandler = new TOrdCollection; fTimers = new TOrdCollection; @@ -536,8 +528,7 @@ Long_t TSystem::NextTimeOut(Bool_t mode) void TSystem::AddSignalHandler(TSignalHandler *h) { - if (h && fSignalHandler && (fSignalHandler->FindObject(h) == 0)) - fSignalHandler->Add(h); + gSigHandling->AddSignalHandler(h); } //////////////////////////////////////////////////////////////////////////////// @@ -546,10 +537,7 @@ void TSystem::AddSignalHandler(TSignalHandler *h) TSignalHandler *TSystem::RemoveSignalHandler(TSignalHandler *h) { - if (fSignalHandler) - return (TSignalHandler *)fSignalHandler->Remove(h); - - return 0; + return (TSignalHandler *)gSigHandling->RemoveSignalHandler(h); } //////////////////////////////////////////////////////////////////////////////// @@ -609,6 +597,17 @@ void TSystem::IgnoreInterrupt(Bool_t ignore) IgnoreSignal(kSigInterrupt, ignore); } +//////////////////////////////////////////////////////////////////////////////// +/// Obtain the current signal handlers +TSeqCollection *TSystem::GetListOfSignalHandlers() +{ + AbstractMethod("GetListOfSignalHandlers"); + return 0; +// TSeqCollection *handler; +// handler = (TSeqCollection *)gSigHandling->GetListOfSignalHandlers(); +// return handler; +} + //////////////////////////////////////////////////////////////////////////////// /// Add an exception handler to list of system exception handlers. Only adds /// the handler if it is not already in the list of exception handlers. diff --git a/core/unix/CMakeLists.txt b/core/unix/CMakeLists.txt index dc4768b1b0040..aa0f9bfedca17 100644 --- a/core/unix/CMakeLists.txt +++ b/core/unix/CMakeLists.txt @@ -4,7 +4,7 @@ ROOT_GLOB_SOURCES(sources ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cxx) -set(Unix_dict_headers ${CMAKE_CURRENT_SOURCE_DIR}/inc/TUnixSystem.h PARENT_SCOPE) +set(Unix_dict_headers ${CMAKE_CURRENT_SOURCE_DIR}/inc/T*.h PARENT_SCOPE) include_directories(${CMAKE_SOURCE_DIR}/net/net/inc) ROOT_OBJECT_LIBRARY(Unix ${sources}) diff --git a/core/unix/inc/LinkDef.h b/core/unix/inc/LinkDef.h index b62af47c4a59c..e3747abacc43c 100644 --- a/core/unix/inc/LinkDef.h +++ b/core/unix/inc/LinkDef.h @@ -14,6 +14,7 @@ #pragma link off all classes; #pragma link off all functions; +#pragma link C++ class TUnixSigHandling; #pragma link C++ class TUnixSystem; #endif diff --git a/core/unix/inc/TUnixSigHandling.h b/core/unix/inc/TUnixSigHandling.h new file mode 100644 index 0000000000000..8c88af1abe701 --- /dev/null +++ b/core/unix/inc/TUnixSigHandling.h @@ -0,0 +1,73 @@ +// @(#)root/unix:$Id$ +// Author: Fons Rademakers 15/09/95 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TUnixSigHandling +#define ROOT_TUnixSigHandling + + +////////////////////////////////////////////////////////////////////////// +// // +// TUnixSigHandling // +// // +// Class providing an interface to the UNIX Operating System. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TSigHandling +#include "TSigHandling.h" +#endif +#ifndef ROOT_TSysEvtHandler +#include "TSysEvtHandler.h" +#endif +#ifndef ROOT_TTimer +#include "TTimer.h" +#endif + +typedef void (*SigHandler_t)(ESignals); + + +class TUnixSigHandling : public TSigHandling { + +protected: + static void UnixSignal(ESignals sig, SigHandler_t h); + static const char *UnixSigname(ESignals sig); + static void UnixSigAlarmInterruptsSyscalls(Bool_t set); + static void UnixResetSignal(ESignals sig); + static void UnixResetSignals(); + static void UnixIgnoreSignal(ESignals sig, Bool_t ignore); + +public: + TUnixSigHandling(); + virtual ~TUnixSigHandling(); + + //---- Misc ------------------------------------------------- + void Init(); + const char *Getenv(const char *name); + void Exit(int code, Bool_t mode = kTRUE); + + //---- Handling of system events ---------------------------- + Bool_t CheckSignals(Bool_t sync); + Bool_t HaveTrappedSignal(Bool_t pendingOnly); + void DispatchSignals(ESignals sig); + void AddSignalHandler(TSignalHandler *sh); + TSignalHandler *RemoveSignalHandler(TSignalHandler *sh); + void ResetSignal(ESignals sig, Bool_t reset = kTRUE); + void ResetSignals(); + void IgnoreSignal(ESignals sig, Bool_t ignore = kTRUE); + void SigAlarmInterruptsSyscalls(Bool_t set); + + //---- Processes -------------------------------------------- + void StackTrace(); + + ClassDef(TUnixSigHandling,0) //Interface to Unix Signal Handling +}; + +#endif diff --git a/core/unix/inc/TUnixSystem.h b/core/unix/inc/TUnixSystem.h index 3df4f2b1fdc83..b9e540f36cb2d 100644 --- a/core/unix/inc/TUnixSystem.h +++ b/core/unix/inc/TUnixSystem.h @@ -54,12 +54,6 @@ class TUnixSystem : public TSystem { static int UnixSetitimer(Long_t ms); static int UnixSelect(Int_t nfds, TFdSet *readready, TFdSet *writeready, Long_t timeout); - static void UnixSignal(ESignals sig, SigHandler_t h); - static const char *UnixSigname(ESignals sig); - static void UnixSigAlarmInterruptsSyscalls(Bool_t set); - static void UnixResetSignal(ESignals sig); - static void UnixResetSignals(); - static void UnixIgnoreSignal(ESignals sig, Bool_t ignore); static int UnixFilestat(const char *path, FileStat_t &buf); static int UnixFSstat(const char *path, Long_t *id, Long_t *bsize, Long_t *blocks, Long_t *bfree); @@ -94,6 +88,7 @@ class TUnixSystem : public TSystem { //---- Handling of system events ---------------------------- void CheckChilds(); Bool_t CheckSignals(Bool_t sync); + Bool_t HaveTrappedSignal(Bool_t pendingOnly); Bool_t CheckDescriptors(); void DispatchSignals(ESignals sig); void AddSignalHandler(TSignalHandler *sh); @@ -101,6 +96,7 @@ class TUnixSystem : public TSystem { void ResetSignal(ESignals sig, Bool_t reset = kTRUE); void ResetSignals(); void IgnoreSignal(ESignals sig, Bool_t ignore = kTRUE); + TSeqCollection *GetListOfSignalHandlers(); void SigAlarmInterruptsSyscalls(Bool_t set); void AddFileHandler(TFileHandler *fh); TFileHandler *RemoveFileHandler(TFileHandler *fh); diff --git a/core/unix/src/TUnixSigHandling.cxx b/core/unix/src/TUnixSigHandling.cxx new file mode 100644 index 0000000000000..2e89b9840efb6 --- /dev/null +++ b/core/unix/src/TUnixSigHandling.cxx @@ -0,0 +1,756 @@ +// @(#)root/unix:$Id: 887c618d89c4ed436e4034fc133f468fecad651b $ +// Author: Fons Rademakers 15/09/95 + +/************************************************************************* + * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TUnixSigHandling // +// // +// Class providing an interface to the UNIX Operating System. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "RConfigure.h" +#include "RConfig.h" +#include "TUnixSigHandling.h" +#include "TUnixSystem.h" +#include "TROOT.h" +#include "TError.h" +#include "TOrdCollection.h" +#include "TRegexp.h" +#include "TPRegexp.h" +#include "TException.h" +#include "Demangle.h" +#include "TEnv.h" +#include "TSocket.h" +#include "Getline.h" +#include "TInterpreter.h" +#include "TApplication.h" +#include "TObjString.h" +#include "Riostream.h" +#include "TVirtualMutex.h" +#include "TObjArray.h" +#include +#include +#include + +//#define G__OLDEXPAND + +#include +#include +#include +#if defined(R__SUN) || defined(R__AIX) || \ + defined(R__LINUX) || defined(R__SOLARIS) || \ + defined(R__FBSD) || defined(R__OBSD) || \ + defined(R__MACOSX) || defined(R__HURD) +#define HAS_DIRENT +#endif +#ifdef HAS_DIRENT +# include +#else +# include +#endif +#if defined(ULTRIX) || defined(R__SUN) +# include +#endif +#if defined(R__AIX) || defined(R__LINUX) || \ + defined(R__FBSD) || defined(R__OBSD) || \ + defined(R__LYNXOS) || defined(R__MACOSX) || defined(R__HURD) +# include +#endif +#if defined(R__AIX) || defined(R__SOLARIS) +# include +#endif +#if defined(R__LINUX) || defined(R__HURD) +# ifndef SIGSYS +# define SIGSYS SIGUNUSED // SIGSYS does not exist in linux ?? +# endif +#endif +#if defined(R__MACOSX) +# include +# include + extern "C" int statfs(const char *file, struct statfs *buffer); +#elif defined(R__LINUX) || defined(R__HURD) +# include +#elif defined(R__FBSD) || defined(R__OBSD) +# include +# include +#else +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(R__AIX) +# define _XOPEN_EXTENDED_SOURCE +# include +# undef _XOPEN_EXTENDED_SOURCE +# if !defined(_AIX41) && !defined(_AIX43) + // AIX 3.2 doesn't have it +# define HASNOT_INETATON +# endif +#else +# include +#endif +#include +#include +#include +#if defined(R__SOLARIS) +# include +# include +# include +# define HASNOT_INETATON +# ifndef INADDR_NONE +# define INADDR_NONE (UInt_t)-1 +# endif +#endif + +#if defined(R__SOLARIS) +# define HAVE_UTMPX_H +# define UTMP_NO_ADDR +#endif + +#if defined(MAC_OS_X_VERSION_10_5) +# define HAVE_UTMPX_H +# define UTMP_NO_ADDR +#endif + +#if defined(R__FBSD) +# include +# if __FreeBSD_version >= 900007 +# define HAVE_UTMPX_H +# endif +#endif + +#if defined(R__AIX) || defined(R__FBSD) || \ + defined(R__OBSD) || defined(R__LYNXOS) || \ + (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5)) +# define UTMP_NO_ADDR +#endif + +#if (defined(R__AIX) && !defined(_AIX43)) || \ + (defined(R__SUNGCC3) && !defined(__arch64__)) +# define USE_SIZE_T +#elif defined(R__GLIBC) || defined(R__FBSD) || \ + (defined(R__SUNGCC3) && defined(__arch64__)) || \ + defined(R__OBSD) || defined(MAC_OS_X_VERSION_10_4) || \ + (defined(R__AIX) && defined(_AIX43)) || \ + (defined(R__SOLARIS) && defined(_SOCKLEN_T)) +# define USE_SOCKLEN_T +#endif + +#if defined(R__LYNXOS) +extern "C" { + extern int putenv(const char *); + extern int inet_aton(const char *, struct in_addr *); +}; +#endif + +#ifdef HAVE_UTMPX_H +#include +#define STRUCT_UTMP struct utmpx +#else +#include +#define STRUCT_UTMP struct utmp +#endif +#if !defined(UTMP_FILE) && defined(_PATH_UTMP) // 4.4BSD +#define UTMP_FILE _PATH_UTMP +#endif +#if defined(UTMPX_FILE) // Solaris, SysVr4 +#undef UTMP_FILE +#define UTMP_FILE UTMPX_FILE +#endif +#ifndef UTMP_FILE +#define UTMP_FILE "/etc/utmp" +#endif + +// stack trace code +#if (defined(R__LINUX) || defined(R__HURD)) && !defined(R__WINGCC) +# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 +# define HAVE_BACKTRACE_SYMBOLS_FD +# endif +# define HAVE_DLADDR +#endif +#if defined(R__MACOSX) +# if defined(MAC_OS_X_VERSION_10_5) +# define HAVE_BACKTRACE_SYMBOLS_FD +# define HAVE_DLADDR +# else +# define USE_GDB_STACK_TRACE +# endif +#endif + +#ifdef HAVE_BACKTRACE_SYMBOLS_FD +# include +#endif +#ifdef HAVE_DLADDR +# ifndef __USE_GNU +# define __USE_GNU +# endif +# include +#endif + +#ifdef HAVE_BACKTRACE_SYMBOLS_FD + // The maximum stack trace depth for systems where we request the + // stack depth separately (currently glibc-based systems). + static const int kMAX_BACKTRACE_DEPTH = 128; +#endif + +//------------------- Unix TFdSet ---------------------------------------------- +#ifndef HOWMANY +# define HOWMANY(x, y) (((x)+((y)-1))/(y)) +#endif + +const Int_t kNFDBITS = (sizeof(Long_t) * 8); // 8 bits per byte +#ifdef FD_SETSIZE +const Int_t kFDSETSIZE = FD_SETSIZE; // Linux = 1024 file descriptors +#else +const Int_t kFDSETSIZE = 256; // upto 256 file descriptors +#endif + + +class TFdSet { +private: + ULong_t fds_bits[HOWMANY(kFDSETSIZE, kNFDBITS)]; +public: + TFdSet() { memset(fds_bits, 0, sizeof(fds_bits)); } + TFdSet(const TFdSet &org) { memcpy(fds_bits, org.fds_bits, sizeof(org.fds_bits)); } + TFdSet &operator=(const TFdSet &rhs) { if (this != &rhs) { memcpy(fds_bits, rhs.fds_bits, sizeof(rhs.fds_bits));} return *this; } + void Zero() { memset(fds_bits, 0, sizeof(fds_bits)); } + void Set(Int_t n) + { + if (n >= 0 && n < kFDSETSIZE) { + fds_bits[n/kNFDBITS] |= (1UL << (n % kNFDBITS)); + } else { + ::Fatal("TFdSet::Set","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); + } + } + void Clr(Int_t n) + { + if (n >= 0 && n < kFDSETSIZE) { + fds_bits[n/kNFDBITS] &= ~(1UL << (n % kNFDBITS)); + } else { + ::Fatal("TFdSet::Clr","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); + } + } + Int_t IsSet(Int_t n) + { + if (n >= 0 && n < kFDSETSIZE) { + return (fds_bits[n/kNFDBITS] & (1UL << (n % kNFDBITS))) != 0; + } else { + ::Fatal("TFdSet::IsSet","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); + return 0; + } + } + ULong_t *GetBits() { return (ULong_t *)fds_bits; } +}; + +#if defined(HAVE_DLADDR) && !defined(R__MACOSX) +//////////////////////////////////////////////////////////////////////////////// + +static void SetRootSys() +{ +#ifndef ROOTPREFIX + void *addr = (void *)SetRootSys; + Dl_info info; + if (dladdr(addr, &info) && info.dli_fname && info.dli_fname[0]) { + char respath[kMAXPATHLEN]; + if (!realpath(info.dli_fname, respath)) { + if (!gSystem->Getenv("ROOTSYS")) + ::SysError("TUnixSigHandling::SetRootSys", "error getting realpath of libCore, please set ROOTSYS in the shell"); + } else { + TString rs = gSystem->DirName(respath); + gSystem->Setenv("ROOTSYS", gSystem->DirName(rs)); + } + } +#else + return; +#endif +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// Unix signal handler. + +static void SigHandler(ESignals sig) +{ + if (gSigHandling) + ((TUnixSigHandling*)gSigHandling)->DispatchSignals(sig); +} + +ClassImp(TUnixSigHandling) + +//////////////////////////////////////////////////////////////////////////////// + +TUnixSigHandling::TUnixSigHandling() : TSigHandling("Unix", "Unix Signal Handling") +{ } + +//////////////////////////////////////////////////////////////////////////////// +/// Reset to original state. + +TUnixSigHandling::~TUnixSigHandling() +{ + UnixResetSignals(); + delete fSignals; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Initialize Unix system interface. + +void TUnixSigHandling::Init() +{ + TSigHandling::Init(); + + fSignals = new TFdSet; + + //--- install default handlers + UnixSignal(kSigChild, SigHandler); + UnixSignal(kSigBus, SigHandler); + UnixSignal(kSigSegmentationViolation, SigHandler); + UnixSignal(kSigIllegalInstruction, SigHandler); + UnixSignal(kSigSystem, SigHandler); + UnixSignal(kSigPipe, SigHandler); + UnixSignal(kSigAlarm, SigHandler); + UnixSignal(kSigUrgent, SigHandler); + UnixSignal(kSigFloatingException, SigHandler); + UnixSignal(kSigWindowChanged, SigHandler); + +#if defined(R__MACOSX) + // trap loading of all dylibs to register dylib name, + // sets also ROOTSYS if built without ROOTPREFIX + _dyld_register_func_for_add_image(DylibAdded); +#elif defined(HAVE_DLADDR) + SetRootSys(); +#endif + +#ifndef ROOTPREFIX + gRootDir = Getenv("ROOTSYS"); + if (gRootDir == 0) + gRootDir= "/usr/local/root"; +#else + gRootDir = ROOTPREFIX; +#endif + +} + +//---- Misc -------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// Get environment variable. + +const char *TUnixSigHandling::Getenv(const char *name) +{ + return ::getenv(name); +} + +//////////////////////////////////////////////////////////////////////////////// +///// Exit the application. + +void TUnixSigHandling::Exit(int code, Bool_t mode) +{ + // Insures that the files and sockets are closed before any library is unloaded + // and before emptying CINT. + if (gROOT) { + gROOT->EndOfProcessCleanups(); + } else if (gInterpreter) { + gInterpreter->ResetGlobals(); + } + + if (mode) + ::exit(code); + else + ::_exit(code); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Add a signal handler to list of system signal handlers. Only adds +/// the handler if it is not already in the list of signal handlers. + +void TUnixSigHandling::AddSignalHandler(TSignalHandler *h) +{ + R__LOCKGUARD2(gSystemMutex); + + if (h && fSignalHandler && (fSignalHandler->FindObject(h) == 0)) + fSignalHandler->Add(h); + + UnixSignal(h->GetSignal(), SigHandler); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Remove a signal handler from list of signal handlers. Returns +/// the handler or 0 if the handler was not in the list of signal handlers. + +TSignalHandler *TUnixSigHandling::RemoveSignalHandler(TSignalHandler *h) +{ + if (!h) return 0; + + R__LOCKGUARD2(gSystemMutex); + + TSignalHandler *oh; + + if (fSignalHandler) + oh = (TSignalHandler *)fSignalHandler->Remove(h); + else + oh = 0; + + Bool_t last = kTRUE; + TSignalHandler *hs; + TIter next(fSignalHandler); + + while ((hs = (TSignalHandler*) next())) { + if (hs->GetSignal() == h->GetSignal()) + last = kFALSE; + } + if (last) + ResetSignal(h->GetSignal(), kTRUE); + + return oh; +} + +//////////////////////////////////////////////////////////////////////////////// +/// If reset is true reset the signal handler for the specified signal +/// to the default handler, else restore previous behaviour. + +void TUnixSigHandling::ResetSignal(ESignals sig, Bool_t reset) +{ + if (reset) + UnixResetSignal(sig); + else + UnixSignal(sig, SigHandler); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Reset signals handlers to previous behaviour. + +void TUnixSigHandling::ResetSignals() +{ + UnixResetSignals(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// If ignore is true ignore the specified signal, else restore previous +/// behaviour. + +void TUnixSigHandling::IgnoreSignal(ESignals sig, Bool_t ignore) +{ + UnixIgnoreSignal(sig, ignore); +} + +//////////////////////////////////////////////////////////////////////////////// +/// When the argument is true the SIGALRM signal handler is set so that +/// interrupted syscalls will not be restarted by the kernel. This is +/// typically used in case one wants to put a timeout on an I/O operation. +/// By default interrupted syscalls will always be restarted (for all +/// signals). This can be controlled for each a-synchronous TTimer via +/// the method TTimer::SetInterruptSyscalls(). + +void TUnixSigHandling::SigAlarmInterruptsSyscalls(Bool_t set) +{ + UnixSigAlarmInterruptsSyscalls(set); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Check if there is any signal trapping. +Bool_t TUnixSigHandling::HaveTrappedSignal(Bool_t pendingOnly) +{ + if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) + if (CheckSignals(kTRUE)) + if (!pendingOnly) return 1; + fSigcnt = 0; + fSignals->Zero(); + return 0; +} + +//---- handling of system events ----------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// Check if some signals were raised and call their Notify() member. + +Bool_t TUnixSigHandling::CheckSignals(Bool_t sync) +{ + TSignalHandler *sh; + Int_t sigdone = -1; + { + TOrdCollectionIter it((TOrdCollection*)fSignalHandler); + + while ((sh = (TSignalHandler*)it.Next())) { + if (sync == sh->IsSync()) { + ESignals sig = sh->GetSignal(); + if ((fSignals->IsSet(sig) && sigdone == -1) || sigdone == sig) { + if (sigdone == -1) { + fSignals->Clr(sig); + sigdone = sig; + fSigcnt--; + } + if (sh->IsActive()) + sh->Notify(); + } + } + } + } + if (sigdone != -1) + return kTRUE; + + return kFALSE; +} + +////////////////////////////////////////////////////////////////////////// +// // +// Static Protected Unix Interface functions. // +// // +////////////////////////////////////////////////////////////////////////// + +//---- signals ----------------------------------------------------------------- + +static struct Signalmap_t { + int fCode; + SigHandler_t fHandler; + struct sigaction *fOldHandler; + const char *fSigName; +} gSignalMap[kMAXSIGNALS] = { // the order of the signals should be identical + { SIGBUS, 0, 0, "bus error" }, // to the one in TSysEvtHandler.h + { SIGSEGV, 0, 0, "segmentation violation" }, + { SIGSYS, 0, 0, "bad argument to system call" }, + { SIGPIPE, 0, 0, "write on a pipe with no one to read it" }, + { SIGILL, 0, 0, "illegal instruction" }, + { SIGQUIT, 0, 0, "quit" }, + { SIGINT, 0, 0, "interrupt" }, + { SIGWINCH, 0, 0, "window size change" }, + { SIGALRM, 0, 0, "alarm clock" }, + { SIGCHLD, 0, 0, "death of a child" }, + { SIGURG, 0, 0, "urgent data arrived on an I/O channel" }, + { SIGFPE, 0, 0, "floating point exception" }, + { SIGTERM, 0, 0, "termination signal" }, + { SIGUSR1, 0, 0, "user-defined signal 1" }, + { SIGUSR2, 0, 0, "user-defined signal 2" } +}; + + +//////////////////////////////////////////////////////////////////////////////// +/// Call the signal handler associated with the signal. + +static void sighandler(int sig) +{ + for (int i= 0; i < kMAXSIGNALS; i++) { + if (gSignalMap[i].fCode == sig) { + (*gSignalMap[i].fHandler)((ESignals)i); + return; + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Handle and dispatch signals. + +void TUnixSigHandling::DispatchSignals(ESignals sig) +{ + switch (sig) { + case kSigAlarm: +// DispatchTimers(kFALSE); + break; + case kSigChild: +// CheckChilds(); + break; + case kSigBus: + case kSigSegmentationViolation: + case kSigIllegalInstruction: + case kSigFloatingException: + Break("TUnixSigHandling::DispatchSignals", "%s", UnixSigname(sig)); + StackTrace(); + if (gApplication) + //sig is ESignal, should it be mapped to the correct signal number? + gApplication->HandleException(sig); + else + //map to the real signal code + set the + //high order bit to indicate a signal (?) + Exit(gSignalMap[sig].fCode + 0x80); + break; + case kSigSystem: + case kSigPipe: + Break("TUnixSigHandling::DispatchSignals", "%s", UnixSigname(sig)); + break; + case kSigWindowChanged: + Gl_windowchanged(); + break; + default: + fSignals->Set(sig); + fSigcnt++; + break; + } + + // check a-synchronous signals + if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) + CheckSignals(kFALSE); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set a signal handler for a signal. + +void TUnixSigHandling::UnixSignal(ESignals sig, SigHandler_t handler) +{ + if (gEnv && !gEnv->GetValue("Root.ErrorHandlers", 1)) + return; + + if (gSignalMap[sig].fHandler != handler) { + struct sigaction sigact; + + gSignalMap[sig].fHandler = handler; + gSignalMap[sig].fOldHandler = new struct sigaction(); + +#if defined(R__SUN) + sigact.sa_handler = (void (*)())sighandler; +#elif defined(R__SOLARIS) + sigact.sa_handler = sighandler; +#elif defined(R__LYNXOS) +# if (__GNUG__>=3) + sigact.sa_handler = sighandler; +# else + sigact.sa_handler = (void (*)(...))sighandler; +# endif +#else + sigact.sa_handler = sighandler; +#endif + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; +#if defined(SA_RESTART) + sigact.sa_flags |= SA_RESTART; +#endif + if (sigaction(gSignalMap[sig].fCode, &sigact, + gSignalMap[sig].fOldHandler) < 0) + ::SysError("TUnixSigHandling::UnixSignal", "sigaction"); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// If ignore is true ignore the specified signal, else restore previous +/// behaviour. + +void TUnixSigHandling::UnixIgnoreSignal(ESignals sig, Bool_t ignore) +{ + TTHREAD_TLS(Bool_t) ignoreSig[kMAXSIGNALS] = { kFALSE }; + TTHREAD_TLS_ARRAY(struct sigaction,kMAXSIGNALS,oldsigact); + + if (ignore != ignoreSig[sig]) { + ignoreSig[sig] = ignore; + if (ignore) { + struct sigaction sigact; +#if defined(R__SUN) + sigact.sa_handler = (void (*)())SIG_IGN; +#elif defined(R__SOLARIS) + sigact.sa_handler = (void (*)(int))SIG_IGN; +#else + sigact.sa_handler = SIG_IGN; +#endif + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + if (sigaction(gSignalMap[sig].fCode, &sigact, &oldsigact[sig]) < 0) + ::SysError("TUnixSigHandling::UnixIgnoreSignal", "sigaction"); + } else { + if (sigaction(gSignalMap[sig].fCode, &oldsigact[sig], 0) < 0) + ::SysError("TUnixSigHandling::UnixIgnoreSignal", "sigaction"); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// When the argument is true the SIGALRM signal handler is set so that +/// interrupted syscalls will not be restarted by the kernel. This is +/// typically used in case one wants to put a timeout on an I/O operation. +/// By default interrupted syscalls will always be restarted (for all +/// signals). This can be controlled for each a-synchronous TTimer via +/// the method TTimer::SetInterruptSyscalls(). + +void TUnixSigHandling::UnixSigAlarmInterruptsSyscalls(Bool_t set) +{ + if (gSignalMap[kSigAlarm].fHandler) { + struct sigaction sigact; +#if defined(R__SUN) + sigact.sa_handler = (void (*)())sighandler; +#elif defined(R__SOLARIS) + sigact.sa_handler = sighandler; +#elif defined(R__LYNXOS) +# if (__GNUG__>=3) + sigact.sa_handler = sighandler; +# else + sigact.sa_handler = (void (*)(...))sighandler; +# endif +#else + sigact.sa_handler = sighandler; +#endif + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + if (set) { +#if defined(SA_INTERRUPT) // SunOS + sigact.sa_flags |= SA_INTERRUPT; +#endif + } else { +#if defined(SA_RESTART) + sigact.sa_flags |= SA_RESTART; +#endif + } + if (sigaction(gSignalMap[kSigAlarm].fCode, &sigact, 0) < 0) + ::SysError("TUnixSigHandling::UnixSigAlarmInterruptsSyscalls", "sigaction"); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return the signal name associated with a signal. + +const char *TUnixSigHandling::UnixSigname(ESignals sig) +{ + return gSignalMap[sig].fSigName; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Restore old signal handler for specified signal. + +void TUnixSigHandling::UnixResetSignal(ESignals sig) +{ + if (gSignalMap[sig].fOldHandler) { + // restore old signal handler + if (sigaction(gSignalMap[sig].fCode, gSignalMap[sig].fOldHandler, 0) < 0) + ::SysError("TUnixSigHandling::UnixSignal", "sigaction"); + delete gSignalMap[sig].fOldHandler; + gSignalMap[sig].fOldHandler = 0; + gSignalMap[sig].fHandler = 0; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Restore old signal handlers. + +void TUnixSigHandling::UnixResetSignals() +{ + for (int sig = 0; sig < kMAXSIGNALS; sig++) + UnixResetSignal((ESignals)sig); +} + +/////////////////////////////////////////////////////////////////////////////// +/// Stack Trace + +void TUnixSigHandling::StackTrace() +{ + gSystem->StackTrace(); +} diff --git a/core/unix/src/TUnixSystem.cxx b/core/unix/src/TUnixSystem.cxx index 40faeb23ac58e..a0963d1ed71f9 100644 --- a/core/unix/src/TUnixSystem.cxx +++ b/core/unix/src/TUnixSystem.cxx @@ -20,6 +20,7 @@ #include "RConfigure.h" #include "RConfig.h" #include "TUnixSystem.h" +#include "TUnixSigHandling.h" #include "TROOT.h" #include "TError.h" #include "TOrdCollection.h" @@ -399,15 +400,6 @@ class TFdSet { ULong_t *GetBits() { return (ULong_t *)fds_bits; } }; -//////////////////////////////////////////////////////////////////////////////// -/// Unix signal handler. - -static void SigHandler(ESignals sig) -{ - if (gSystem) - ((TUnixSystem*)gSystem)->DispatchSignals(sig); -} - //////////////////////////////////////////////////////////////////////////////// static const char *GetExePath() @@ -570,13 +562,10 @@ TUnixSystem::TUnixSystem() : TSystem("Unix", "Unix System") TUnixSystem::~TUnixSystem() { - UnixResetSignals(); - delete fReadmask; delete fWritemask; delete fReadready; delete fWriteready; - delete fSignals; } //////////////////////////////////////////////////////////////////////////////// @@ -591,19 +580,9 @@ Bool_t TUnixSystem::Init() fWritemask = new TFdSet; fReadready = new TFdSet; fWriteready = new TFdSet; - fSignals = new TFdSet; //--- install default handlers - UnixSignal(kSigChild, SigHandler); - UnixSignal(kSigBus, SigHandler); - UnixSignal(kSigSegmentationViolation, SigHandler); - UnixSignal(kSigIllegalInstruction, SigHandler); - UnixSignal(kSigSystem, SigHandler); - UnixSignal(kSigPipe, SigHandler); - UnixSignal(kSigAlarm, SigHandler); - UnixSignal(kSigUrgent, SigHandler); - UnixSignal(kSigFloatingException, SigHandler); - UnixSignal(kSigWindowChanged, SigHandler); + gSigHandling->Init(); #if defined(R__MACOSX) // trap loading of all dylibs to register dylib name, @@ -803,10 +782,7 @@ TFileHandler *TUnixSystem::RemoveFileHandler(TFileHandler *h) void TUnixSystem::AddSignalHandler(TSignalHandler *h) { - R__LOCKGUARD2(gSystemMutex); - - TSystem::AddSignalHandler(h); - UnixSignal(h->GetSignal(), SigHandler); + gSigHandling->AddSignalHandler(h); } //////////////////////////////////////////////////////////////////////////////// @@ -815,23 +791,7 @@ void TUnixSystem::AddSignalHandler(TSignalHandler *h) TSignalHandler *TUnixSystem::RemoveSignalHandler(TSignalHandler *h) { - if (!h) return 0; - - R__LOCKGUARD2(gSystemMutex); - - TSignalHandler *oh = TSystem::RemoveSignalHandler(h); - - Bool_t last = kTRUE; - TSignalHandler *hs; - TIter next(fSignalHandler); - - while ((hs = (TSignalHandler*) next())) { - if (hs->GetSignal() == h->GetSignal()) - last = kFALSE; - } - if (last) - ResetSignal(h->GetSignal(), kTRUE); - + TSignalHandler *oh = gSigHandling->RemoveSignalHandler(h); return oh; } @@ -841,10 +801,7 @@ TSignalHandler *TUnixSystem::RemoveSignalHandler(TSignalHandler *h) void TUnixSystem::ResetSignal(ESignals sig, Bool_t reset) { - if (reset) - UnixResetSignal(sig); - else - UnixSignal(sig, SigHandler); + gSigHandling->ResetSignal(sig, reset); } //////////////////////////////////////////////////////////////////////////////// @@ -852,7 +809,7 @@ void TUnixSystem::ResetSignal(ESignals sig, Bool_t reset) void TUnixSystem::ResetSignals() { - UnixResetSignals(); + gSigHandling->ResetSignals(); } //////////////////////////////////////////////////////////////////////////////// @@ -861,7 +818,16 @@ void TUnixSystem::ResetSignals() void TUnixSystem::IgnoreSignal(ESignals sig, Bool_t ignore) { - UnixIgnoreSignal(sig, ignore); + gSigHandling->IgnoreSignal(sig, ignore); +} + +//////////////////////////////////////////////////////////////////////////////// +/// If ignore is true ignore the specified signal, else restore previous +/// behaviour. + +Bool_t TUnixSystem::HaveTrappedSignal(Bool_t pendingOnly) +{ + return gSigHandling->HaveTrappedSignal(pendingOnly); } //////////////////////////////////////////////////////////////////////////////// @@ -874,7 +840,14 @@ void TUnixSystem::IgnoreSignal(ESignals sig, Bool_t ignore) void TUnixSystem::SigAlarmInterruptsSyscalls(Bool_t set) { - UnixSigAlarmInterruptsSyscalls(set); + gSigHandling->SigAlarmInterruptsSyscalls(set); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Obtain the current signal handlers +TSeqCollection *TUnixSystem::GetListOfSignalHandlers() +{ + return (TSeqCollection *)gSigHandling->GetListOfSignalHandlers(); } //////////////////////////////////////////////////////////////////////////////// @@ -1083,11 +1056,7 @@ void TUnixSystem::DispatchOneEvent(Bool_t pendingOnly) return; // check synchronous signals - if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) - if (CheckSignals(kTRUE)) - if (!pendingOnly) return; - fSigcnt = 0; - fSignals->Zero(); + if (HaveTrappedSignal(pendingOnly)) return; // check synchronous timers Long_t nextto; @@ -1247,37 +1216,6 @@ Int_t TUnixSystem::Select(TFileHandler *h, Long_t to) //---- handling of system events ----------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// Check if some signals were raised and call their Notify() member. - -Bool_t TUnixSystem::CheckSignals(Bool_t sync) -{ - TSignalHandler *sh; - Int_t sigdone = -1; - { - TOrdCollectionIter it((TOrdCollection*)fSignalHandler); - - while ((sh = (TSignalHandler*)it.Next())) { - if (sync == sh->IsSync()) { - ESignals sig = sh->GetSignal(); - if ((fSignals->IsSet(sig) && sigdone == -1) || sigdone == sig) { - if (sigdone == -1) { - fSignals->Clr(sig); - sigdone = sig; - fSigcnt--; - } - if (sh->IsActive()) - sh->Notify(); - } - } - } - } - if (sigdone != -1) - return kTRUE; - - return kFALSE; -} - //////////////////////////////////////////////////////////////////////////////// /// Check if children have finished. @@ -3596,237 +3534,6 @@ int TUnixSystem::GetSockOpt(int sock, int opt, int *val) return 0; } -////////////////////////////////////////////////////////////////////////// -// // -// Static Protected Unix Interface functions. // -// // -////////////////////////////////////////////////////////////////////////// - -//---- signals ----------------------------------------------------------------- - -static struct Signalmap_t { - int fCode; - SigHandler_t fHandler; - struct sigaction *fOldHandler; - const char *fSigName; -} gSignalMap[kMAXSIGNALS] = { // the order of the signals should be identical - { SIGBUS, 0, 0, "bus error" }, // to the one in TSysEvtHandler.h - { SIGSEGV, 0, 0, "segmentation violation" }, - { SIGSYS, 0, 0, "bad argument to system call" }, - { SIGPIPE, 0, 0, "write on a pipe with no one to read it" }, - { SIGILL, 0, 0, "illegal instruction" }, - { SIGQUIT, 0, 0, "quit" }, - { SIGINT, 0, 0, "interrupt" }, - { SIGWINCH, 0, 0, "window size change" }, - { SIGALRM, 0, 0, "alarm clock" }, - { SIGCHLD, 0, 0, "death of a child" }, - { SIGURG, 0, 0, "urgent data arrived on an I/O channel" }, - { SIGFPE, 0, 0, "floating point exception" }, - { SIGTERM, 0, 0, "termination signal" }, - { SIGUSR1, 0, 0, "user-defined signal 1" }, - { SIGUSR2, 0, 0, "user-defined signal 2" } -}; - - -//////////////////////////////////////////////////////////////////////////////// -/// Call the signal handler associated with the signal. - -static void sighandler(int sig) -{ - for (int i= 0; i < kMAXSIGNALS; i++) { - if (gSignalMap[i].fCode == sig) { - (*gSignalMap[i].fHandler)((ESignals)i); - return; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Handle and dispatch signals. - -void TUnixSystem::DispatchSignals(ESignals sig) -{ - switch (sig) { - case kSigAlarm: - DispatchTimers(kFALSE); - break; - case kSigChild: - CheckChilds(); - break; - case kSigBus: - case kSigSegmentationViolation: - case kSigIllegalInstruction: - case kSigFloatingException: - Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig)); - StackTrace(); - if (gApplication) - //sig is ESignal, should it be mapped to the correct signal number? - gApplication->HandleException(sig); - else - //map to the real signal code + set the - //high order bit to indicate a signal (?) - Exit(gSignalMap[sig].fCode + 0x80); - break; - case kSigSystem: - case kSigPipe: - Break("TUnixSystem::DispatchSignals", "%s", UnixSigname(sig)); - break; - case kSigWindowChanged: - Gl_windowchanged(); - break; - default: - fSignals->Set(sig); - fSigcnt++; - break; - } - - // check a-synchronous signals - if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) - CheckSignals(kFALSE); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set a signal handler for a signal. - -void TUnixSystem::UnixSignal(ESignals sig, SigHandler_t handler) -{ - if (gEnv && !gEnv->GetValue("Root.ErrorHandlers", 1)) - return; - - if (gSignalMap[sig].fHandler != handler) { - struct sigaction sigact; - - gSignalMap[sig].fHandler = handler; - gSignalMap[sig].fOldHandler = new struct sigaction(); - -#if defined(R__SUN) - sigact.sa_handler = (void (*)())sighandler; -#elif defined(R__SOLARIS) - sigact.sa_handler = sighandler; -#elif defined(R__LYNXOS) -# if (__GNUG__>=3) - sigact.sa_handler = sighandler; -# else - sigact.sa_handler = (void (*)(...))sighandler; -# endif -#else - sigact.sa_handler = sighandler; -#endif - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; -#if defined(SA_RESTART) - sigact.sa_flags |= SA_RESTART; -#endif - if (sigaction(gSignalMap[sig].fCode, &sigact, - gSignalMap[sig].fOldHandler) < 0) - ::SysError("TUnixSystem::UnixSignal", "sigaction"); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// If ignore is true ignore the specified signal, else restore previous -/// behaviour. - -void TUnixSystem::UnixIgnoreSignal(ESignals sig, Bool_t ignore) -{ - TTHREAD_TLS(Bool_t) ignoreSig[kMAXSIGNALS] = { kFALSE }; - TTHREAD_TLS_ARRAY(struct sigaction,kMAXSIGNALS,oldsigact); - - if (ignore != ignoreSig[sig]) { - ignoreSig[sig] = ignore; - if (ignore) { - struct sigaction sigact; -#if defined(R__SUN) - sigact.sa_handler = (void (*)())SIG_IGN; -#elif defined(R__SOLARIS) - sigact.sa_handler = (void (*)(int))SIG_IGN; -#else - sigact.sa_handler = SIG_IGN; -#endif - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - if (sigaction(gSignalMap[sig].fCode, &sigact, &oldsigact[sig]) < 0) - ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction"); - } else { - if (sigaction(gSignalMap[sig].fCode, &oldsigact[sig], 0) < 0) - ::SysError("TUnixSystem::UnixIgnoreSignal", "sigaction"); - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// When the argument is true the SIGALRM signal handler is set so that -/// interrupted syscalls will not be restarted by the kernel. This is -/// typically used in case one wants to put a timeout on an I/O operation. -/// By default interrupted syscalls will always be restarted (for all -/// signals). This can be controlled for each a-synchronous TTimer via -/// the method TTimer::SetInterruptSyscalls(). - -void TUnixSystem::UnixSigAlarmInterruptsSyscalls(Bool_t set) -{ - if (gSignalMap[kSigAlarm].fHandler) { - struct sigaction sigact; -#if defined(R__SUN) - sigact.sa_handler = (void (*)())sighandler; -#elif defined(R__SOLARIS) - sigact.sa_handler = sighandler; -#elif defined(R__LYNXOS) -# if (__GNUG__>=3) - sigact.sa_handler = sighandler; -# else - sigact.sa_handler = (void (*)(...))sighandler; -# endif -#else - sigact.sa_handler = sighandler; -#endif - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - if (set) { -#if defined(SA_INTERRUPT) // SunOS - sigact.sa_flags |= SA_INTERRUPT; -#endif - } else { -#if defined(SA_RESTART) - sigact.sa_flags |= SA_RESTART; -#endif - } - if (sigaction(gSignalMap[kSigAlarm].fCode, &sigact, 0) < 0) - ::SysError("TUnixSystem::UnixSigAlarmInterruptsSyscalls", "sigaction"); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Return the signal name associated with a signal. - -const char *TUnixSystem::UnixSigname(ESignals sig) -{ - return gSignalMap[sig].fSigName; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Restore old signal handler for specified signal. - -void TUnixSystem::UnixResetSignal(ESignals sig) -{ - if (gSignalMap[sig].fOldHandler) { - // restore old signal handler - if (sigaction(gSignalMap[sig].fCode, gSignalMap[sig].fOldHandler, 0) < 0) - ::SysError("TUnixSystem::UnixSignal", "sigaction"); - delete gSignalMap[sig].fOldHandler; - gSignalMap[sig].fOldHandler = 0; - gSignalMap[sig].fHandler = 0; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Restore old signal handlers. - -void TUnixSystem::UnixResetSignals() -{ - for (int sig = 0; sig < kMAXSIGNALS; sig++) - UnixResetSignal((ESignals)sig); -} - //---- time -------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// From e82976ed0ff0d9258673c935c4d5776241b8266a Mon Sep 17 00:00:00 2001 From: Zhe Zhang Date: Wed, 20 Jan 2016 21:40:19 -0600 Subject: [PATCH 2/7] Change functions in signal handlers to be thread-safe --- core/unix/inc/TUnixSigHandling.h | 36 +- core/unix/inc/TUnixSystem.h | 25 ++ core/unix/src/TUnixSigHandling.cxx | 505 +++++++++++++++++++---------- core/unix/src/TUnixSystem.cxx | 71 ++-- 4 files changed, 404 insertions(+), 233 deletions(-) diff --git a/core/unix/inc/TUnixSigHandling.h b/core/unix/inc/TUnixSigHandling.h index 8c88af1abe701..8d446bc1faac0 100644 --- a/core/unix/inc/TUnixSigHandling.h +++ b/core/unix/inc/TUnixSigHandling.h @@ -37,35 +37,45 @@ typedef void (*SigHandler_t)(ESignals); class TUnixSigHandling : public TSigHandling { protected: + //---- Unix signal interface functions ---------------------- static void UnixSignal(ESignals sig, SigHandler_t h); static const char *UnixSigname(ESignals sig); static void UnixSigAlarmInterruptsSyscalls(Bool_t set); static void UnixResetSignal(ESignals sig); static void UnixResetSignals(); static void UnixIgnoreSignal(ESignals sig, Bool_t ignore); + static void UnixSetDefaultSignals(); + //---- Unix stack trace helper functions --------------------- + static void StackTraceHelperInit(); + static void StackTraceMonitorThread(); + static void StackTraceTriggerThread(); + static void StackTraceForkThread(); + static int StackTraceExecScript(void *); + public: TUnixSigHandling(); virtual ~TUnixSigHandling(); //---- Misc ------------------------------------------------- - void Init(); - const char *Getenv(const char *name); - void Exit(int code, Bool_t mode = kTRUE); + static const char *Getenv(const char *name); + static int GetPid(); + static void Exit(int code, Bool_t mode = kTRUE); + void Init(); //---- Handling of system events ---------------------------- - Bool_t CheckSignals(Bool_t sync); - Bool_t HaveTrappedSignal(Bool_t pendingOnly); - void DispatchSignals(ESignals sig); - void AddSignalHandler(TSignalHandler *sh); - TSignalHandler *RemoveSignalHandler(TSignalHandler *sh); - void ResetSignal(ESignals sig, Bool_t reset = kTRUE); - void ResetSignals(); - void IgnoreSignal(ESignals sig, Bool_t ignore = kTRUE); - void SigAlarmInterruptsSyscalls(Bool_t set); + Bool_t CheckSignals(Bool_t sync); + Bool_t HaveTrappedSignal(Bool_t pendingOnly); + void DispatchSignals(ESignals sig); + void AddSignalHandler(TSignalHandler *sh); + TSignalHandler *RemoveSignalHandler(TSignalHandler *sh); + void ResetSignal(ESignals sig, Bool_t reset = kTRUE); + void ResetSignals(); + void IgnoreSignal(ESignals sig, Bool_t ignore = kTRUE); + void SigAlarmInterruptsSyscalls(Bool_t set); //---- Processes -------------------------------------------- - void StackTrace(); + void StackTrace(); ClassDef(TUnixSigHandling,0) //Interface to Unix Signal Handling }; diff --git a/core/unix/inc/TUnixSystem.h b/core/unix/inc/TUnixSystem.h index b9e540f36cb2d..5016c77e014f2 100644 --- a/core/unix/inc/TUnixSystem.h +++ b/core/unix/inc/TUnixSystem.h @@ -33,6 +33,31 @@ typedef void (*SigHandler_t)(ESignals); +//------------------- Unix TFdSet ---------------------------------------------- +#ifndef HOWMANY +# define HOWMANY(x, y) (((x)+((y)-1))/(y)) +#endif + +const Int_t kNFDBITS = (sizeof(Long_t) * 8); // 8 bits per byte +#ifdef FD_SETSIZE +const Int_t kFDSETSIZE = FD_SETSIZE; // Linux = 1024 file descriptors +#else +const Int_t kFDSETSIZE = 256; // upto 256 file descriptors +#endif + +class TFdSet { +private: + ULong_t fds_bits[HOWMANY(kFDSETSIZE, kNFDBITS)]; +public: + TFdSet(); + TFdSet(const TFdSet &org); + TFdSet &operator=(const TFdSet &rhs) { if (this != &rhs) { memcpy(fds_bits, rhs.fds_bits, sizeof(rhs.fds_bits));} return *this; } + void Zero(); + void Set(Int_t n); + void Clr(Int_t n); + Int_t IsSet(Int_t n); + ULong_t *GetBits(); +}; class TUnixSystem : public TSystem { diff --git a/core/unix/src/TUnixSigHandling.cxx b/core/unix/src/TUnixSigHandling.cxx index 2e89b9840efb6..c4e00421733d8 100644 --- a/core/unix/src/TUnixSigHandling.cxx +++ b/core/unix/src/TUnixSigHandling.cxx @@ -23,15 +23,9 @@ #include "TUnixSystem.h" #include "TROOT.h" #include "TError.h" -#include "TOrdCollection.h" -#include "TRegexp.h" -#include "TPRegexp.h" -#include "TException.h" -#include "Demangle.h" #include "TEnv.h" -#include "TSocket.h" #include "Getline.h" -#include "TInterpreter.h" +#include "TOrdCollection.h" #include "TApplication.h" #include "TObjString.h" #include "Riostream.h" @@ -40,31 +34,24 @@ #include #include #include +#include +#include +#include + +#ifdef __linux__ +#include +#endif //#define G__OLDEXPAND #include #include -#include -#if defined(R__SUN) || defined(R__AIX) || \ - defined(R__LINUX) || defined(R__SOLARIS) || \ - defined(R__FBSD) || defined(R__OBSD) || \ - defined(R__MACOSX) || defined(R__HURD) -#define HAS_DIRENT -#endif -#ifdef HAS_DIRENT -# include -#else -# include -#endif -#if defined(ULTRIX) || defined(R__SUN) -# include -#endif -#if defined(R__AIX) || defined(R__LINUX) || \ - defined(R__FBSD) || defined(R__OBSD) || \ - defined(R__LYNXOS) || defined(R__MACOSX) || defined(R__HURD) -# include + +#ifndef R__WIN32 +#include #endif + +#include #if defined(R__AIX) || defined(R__SOLARIS) # include #endif @@ -73,118 +60,14 @@ # define SIGSYS SIGUNUSED // SIGSYS does not exist in linux ?? # endif #endif -#if defined(R__MACOSX) -# include -# include - extern "C" int statfs(const char *file, struct statfs *buffer); -#elif defined(R__LINUX) || defined(R__HURD) -# include -#elif defined(R__FBSD) || defined(R__OBSD) -# include -# include -#else -# include -#endif #include -#include -#include -#include #include -#include -#include -#include #include #include #include #include #include -#include -#include -#include -#include -#if defined(R__AIX) -# define _XOPEN_EXTENDED_SOURCE -# include -# undef _XOPEN_EXTENDED_SOURCE -# if !defined(_AIX41) && !defined(_AIX43) - // AIX 3.2 doesn't have it -# define HASNOT_INETATON -# endif -#else -# include -#endif -#include -#include -#include -#if defined(R__SOLARIS) -# include -# include -# include -# define HASNOT_INETATON -# ifndef INADDR_NONE -# define INADDR_NONE (UInt_t)-1 -# endif -#endif - -#if defined(R__SOLARIS) -# define HAVE_UTMPX_H -# define UTMP_NO_ADDR -#endif - -#if defined(MAC_OS_X_VERSION_10_5) -# define HAVE_UTMPX_H -# define UTMP_NO_ADDR -#endif - -#if defined(R__FBSD) -# include -# if __FreeBSD_version >= 900007 -# define HAVE_UTMPX_H -# endif -#endif - -#if defined(R__AIX) || defined(R__FBSD) || \ - defined(R__OBSD) || defined(R__LYNXOS) || \ - (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5)) -# define UTMP_NO_ADDR -#endif - -#if (defined(R__AIX) && !defined(_AIX43)) || \ - (defined(R__SUNGCC3) && !defined(__arch64__)) -# define USE_SIZE_T -#elif defined(R__GLIBC) || defined(R__FBSD) || \ - (defined(R__SUNGCC3) && defined(__arch64__)) || \ - defined(R__OBSD) || defined(MAC_OS_X_VERSION_10_4) || \ - (defined(R__AIX) && defined(_AIX43)) || \ - (defined(R__SOLARIS) && defined(_SOCKLEN_T)) -# define USE_SOCKLEN_T -#endif - -#if defined(R__LYNXOS) -extern "C" { - extern int putenv(const char *); - extern int inet_aton(const char *, struct in_addr *); -}; -#endif - -#ifdef HAVE_UTMPX_H -#include -#define STRUCT_UTMP struct utmpx -#else -#include -#define STRUCT_UTMP struct utmp -#endif -#if !defined(UTMP_FILE) && defined(_PATH_UTMP) // 4.4BSD -#define UTMP_FILE _PATH_UTMP -#endif -#if defined(UTMPX_FILE) // Solaris, SysVr4 -#undef UTMP_FILE -#define UTMP_FILE UTMPX_FILE -#endif -#ifndef UTMP_FILE -#define UTMP_FILE "/etc/utmp" -#endif // stack trace code #if (defined(R__LINUX) || defined(R__HURD)) && !defined(R__WINGCC) @@ -218,55 +101,8 @@ extern "C" { static const int kMAX_BACKTRACE_DEPTH = 128; #endif -//------------------- Unix TFdSet ---------------------------------------------- -#ifndef HOWMANY -# define HOWMANY(x, y) (((x)+((y)-1))/(y)) -#endif - -const Int_t kNFDBITS = (sizeof(Long_t) * 8); // 8 bits per byte -#ifdef FD_SETSIZE -const Int_t kFDSETSIZE = FD_SETSIZE; // Linux = 1024 file descriptors -#else -const Int_t kFDSETSIZE = 256; // upto 256 file descriptors -#endif - - -class TFdSet { -private: - ULong_t fds_bits[HOWMANY(kFDSETSIZE, kNFDBITS)]; -public: - TFdSet() { memset(fds_bits, 0, sizeof(fds_bits)); } - TFdSet(const TFdSet &org) { memcpy(fds_bits, org.fds_bits, sizeof(org.fds_bits)); } - TFdSet &operator=(const TFdSet &rhs) { if (this != &rhs) { memcpy(fds_bits, rhs.fds_bits, sizeof(rhs.fds_bits));} return *this; } - void Zero() { memset(fds_bits, 0, sizeof(fds_bits)); } - void Set(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - fds_bits[n/kNFDBITS] |= (1UL << (n % kNFDBITS)); - } else { - ::Fatal("TFdSet::Set","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - } - } - void Clr(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - fds_bits[n/kNFDBITS] &= ~(1UL << (n % kNFDBITS)); - } else { - ::Fatal("TFdSet::Clr","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - } - } - Int_t IsSet(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - return (fds_bits[n/kNFDBITS] & (1UL << (n % kNFDBITS))) != 0; - } else { - ::Fatal("TFdSet::IsSet","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - return 0; - } - } - ULong_t *GetBits() { return (ULong_t *)fds_bits; } -}; - +class TFdSet; + #if defined(HAVE_DLADDR) && !defined(R__MACOSX) //////////////////////////////////////////////////////////////////////////////// @@ -300,6 +136,123 @@ static void SigHandler(ESignals sig) ((TUnixSigHandling*)gSigHandling)->DispatchSignals(sig); } +//////////////////////////////////////////////////////////////////////////////// +/// Async-signal-safe Write functions. + +static int SignalSafeWrite(int fd, const char *text) { + const char *buffer = text; + size_t count = strlen(text); + ssize_t written = 0; + while (count) { + written = write(fd, buffer, count); + if (written == -1) { + if (errno == EINTR) { continue; } + else { return -errno; } + } + count -= written; + buffer += written; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Async-signal-safe Read functions. + +static int SignalSafeRead(int fd, char *inbuf, size_t len, int timeout=-1) { + char *buf = inbuf; + size_t count = len; + ssize_t complete = 0; + std::chrono::time_point endTime = std::chrono::steady_clock::now() + std::chrono::seconds(timeout); + int flags; + if (timeout < 0) { + flags = O_NONBLOCK; // Prevents us from trying to set / restore flags later. + } else if ((-1 == (flags = fcntl(fd, F_GETFL)))) { + return -errno; + } else { } + if ((flags & O_NONBLOCK) != O_NONBLOCK) { + if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + return -errno; + } + } + while (count) { + if (timeout >= 0) { + struct pollfd pollInfo{fd, POLLIN, 0}; + int msRemaining = std::chrono::duration_cast(endTime-std::chrono::steady_clock::now()).count(); + if (msRemaining > 0) { + if (poll(&pollInfo, 1, msRemaining) == 0) { + if ((flags & O_NONBLOCK) != O_NONBLOCK) { + fcntl(fd, F_SETFL, flags); + } + return -ETIMEDOUT; + } + } else if (msRemaining < 0) { + if ((flags & O_NONBLOCK) != O_NONBLOCK) { + fcntl(fd, F_SETFL, flags); + } + return -ETIMEDOUT; + } else { } + } + complete = read(fd, buf, count); + if (complete == -1) { + if (errno == EINTR) { continue; } + else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { continue; } + else { + int origErrno = errno; + if ((flags & O_NONBLOCK) != O_NONBLOCK) { + fcntl(fd, F_SETFL, flags); + } + return -origErrno; + } + } + count -= complete; + buf += complete; + } + if ((flags & O_NONBLOCK) != O_NONBLOCK) { + fcntl(fd, F_SETFL, flags); + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Async-signal-safe Write Error functions. + +static int SignalSafeErrWrite(const char *text) { + return SignalSafeWrite(2, text); +} + +////////////////////////////////////////////////////////////////////////// +// // +// Static Protected Unix StackTrace functions. // +// // +////////////////////////////////////////////////////////////////////////// + +//---- 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 char * const kStackArgv[] = {gStackTraceHelper.fShellExec, gStackTraceHelper.fPidString, gStackTraceHelper.fPidNum, nullptr}; + +////////////////////////////////////////////////////////////////////////////// +static char * const *GetStackArgv() { + return kStackArgv; +} + ClassImp(TUnixSigHandling) //////////////////////////////////////////////////////////////////////////////// @@ -353,6 +306,29 @@ void TUnixSigHandling::Init() gRootDir = ROOTPREFIX; #endif + if(snprintf(gStackTraceHelper.fShellExec, kStringLength-1, "/bin/sh") >= kStringLength) { + SignalSafeErrWrite("Unable to pre-allocate shell command path"); + return; + } + +#ifdef ROOTETCDIR + if(snprintf(gStackTraceHelper.fPidString, kStringLength-1, "%s/gdb-backtrace.sh", ROOTETCDIR) >= kStringLength) { + SignalSafeErrWrite("Unable to pre-allocate executable information"); + return; + } +#else + if(snprintf(gStackTraceHelper.fPidString, kStringLength-1, "%s/etc/gdb-backtrace.sh", gSystem->Getenv("ROOTSYS")) >= kStringLength) { + 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(); } //---- Misc -------------------------------------------------------------------- @@ -365,6 +341,14 @@ const char *TUnixSigHandling::Getenv(const char *name) return ::getenv(name); } +//////////////////////////////////////////////////////////////////////////////// +/// Get process id. + +int TUnixSigHandling::GetPid() +{ + return ::getpid(); +} + //////////////////////////////////////////////////////////////////////////////// ///// Exit the application. @@ -574,8 +558,14 @@ void TUnixSigHandling::DispatchSignals(ESignals sig) // CheckChilds(); break; case kSigBus: + SignalSafeErrWrite("\n\nA fatal system signal has occurred: bus error"); + break; case kSigSegmentationViolation: + SignalSafeErrWrite("\n\nA fatal system signal has occurred: segmentation violation error"); + break; case kSigIllegalInstruction: + SignalSafeErrWrite("\n\nA fatal system signal has occurred: illegal instruction error"); + break; case kSigFloatingException: Break("TUnixSigHandling::DispatchSignals", "%s", UnixSigname(sig)); StackTrace(); @@ -600,6 +590,13 @@ void TUnixSigHandling::DispatchSignals(ESignals sig) break; } + if ((sig == kSigIllegalInstruction) || (sig == kSigSegmentationViolation) || (sig == kSigBus)) + { + StackTraceTriggerThread(); + signal(sig, SIG_DFL); + raise(sig); + } + // check a-synchronous signals if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) CheckSignals(kFALSE); @@ -747,6 +744,16 @@ void TUnixSigHandling::UnixResetSignals() UnixResetSignal((ESignals)sig); } +//////////////////////////////////////////////////////////////////////////////// +/// Set signal handlers to default signal handlers + +void TUnixSigHandling::UnixSetDefaultSignals() +{ + signal(SIGILL, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGBUS, SIG_DFL); +} + /////////////////////////////////////////////////////////////////////////////// /// Stack Trace @@ -754,3 +761,143 @@ void TUnixSigHandling::StackTrace() { gSystem->StackTrace(); } + +////////////////////////////////////////////////////////////////////////////// +/// Initialize StackTrace helper structures + +void TUnixSigHandling::StackTraceHelperInit() +{ + if(snprintf(gStackTraceHelper.fPidNum, kStringLength-1, "%d", GetPid()) >= kStringLength) { + SignalSafeErrWrite("Unable to pre-allocate process id information"); + return; + } + + close(gStackTraceHelper.fChildToParent[0]); + close(gStackTraceHelper.fChildToParent[1]); + gStackTraceHelper.fChildToParent[0] = -1; gStackTraceHelper.fChildToParent[1] = -1; + close(gStackTraceHelper.fParentToChild[0]); + close(gStackTraceHelper.fParentToChild[1]); + gStackTraceHelper.fParentToChild[0] = -1; gStackTraceHelper.fParentToChild[1] = -1; + + if (-1 == pipe2(gStackTraceHelper.fChildToParent, O_CLOEXEC)) { + fprintf(stdout, "pipe gStackTraceHelper.fChildToParent failed\n"); + return; + } + if (-1 == pipe2(gStackTraceHelper.fParentToChild, O_CLOEXEC)){ + close(gStackTraceHelper.fChildToParent[0]); close(gStackTraceHelper.fChildToParent[1]); + gStackTraceHelper.fChildToParent[0] = -1; gStackTraceHelper.fChildToParent[1] = -1; + fprintf(stdout, "pipe parentToChild failed\n"); + return; + } + + gStackTraceHelper.fHelperThread.reset(new std::thread(StackTraceMonitorThread)); + gStackTraceHelper.fHelperThread->detach(); +} + +////////////////////////////////////////////////////////////////////////////// +/// StackTrace helper thread to monitor the signal interrupts + +void TUnixSigHandling::StackTraceMonitorThread() +{ + int toParent = gStackTraceHelper.fChildToParent[1]; + int fromParent = gStackTraceHelper.fParentToChild[0]; + char buf[2]; buf[1] = '\0'; + while(true) { + int result = SignalSafeRead(fromParent, buf, 1, 5*60); + if (result < 0) { + UnixSetDefaultSignals(); + close(toParent); + SignalSafeErrWrite("\n\nTraceback helper thread failed to read from parent: "); + SignalSafeErrWrite(strerror(-result)); + SignalSafeErrWrite("\n"); + Exit(1, kFALSE); + } + if (buf[0] == '1') { + UnixSetDefaultSignals(); + StackTraceForkThread(); + SignalSafeWrite(toParent, buf); + } else if (buf[0] == '2') { + close(toParent); + close(fromParent); + toParent = gStackTraceHelper.fChildToParent[1]; + fromParent = gStackTraceHelper.fParentToChild[0]; + } else if (buf[0] == '3') { + break; + } else { + UnixSetDefaultSignals(); + close(toParent); + SignalSafeErrWrite("\n\nTraceback helper thread got unknown command from parent: "); + SignalSafeErrWrite(buf); + SignalSafeErrWrite("\n"); + Exit(1, kFALSE); + } + } + return; +} + +////////////////////////////////////////////////////////////////////////////// +/// One of StackTrace helper threads. +/// This thread is to trigger the monitor thread by pipe. + +void TUnixSigHandling::StackTraceTriggerThread() +{ + int result = SignalSafeWrite(gStackTraceHelper.fParentToChild[1], "1"); + if (result < 0) { + SignalSafeErrWrite("\n\nAttempt to request stacktrace failed: "); + SignalSafeErrWrite(strerror(-result)); + SignalSafeErrWrite("\n"); + return; + } + char buf[2]; buf[1] = '\0'; + if ((result = SignalSafeRead(gStackTraceHelper.fChildToParent[0], buf, 1)) < 0) { + SignalSafeErrWrite("\n\nWaiting for stacktrace completion failed: "); + SignalSafeErrWrite(strerror(-result)); + SignalSafeErrWrite("\n"); + return; + } +} + +////////////////////////////////////////////////////////////////////////////// +/// One of StackTrace helper threads. +/// This thread is to fork a new thread in order to print out StackTrace info. + +void TUnixSigHandling::StackTraceForkThread() +{ + char childStack[4*1024]; + char *childStackPtr = childStack + 4*1024; + int pid = +#ifdef __linux__ + clone(StackTraceExecScript, childStackPtr, CLONE_VM|CLONE_FS|SIGCHLD, nullptr); +#else + fork(); + if (childStackPtr) {} // Suppress 'unused variable' warning on non-Linux + if (pid == 0) { StackTraceExecScript(nullptr); Exit(0, kFALSE); } +#endif + if (pid == -1) { + SignalSafeErrWrite("(Attempt to perform stack dump failed.)\n"); + } else { + int status; + if (waitpid(pid, &status, 0) == -1) { + SignalSafeErrWrite("(Failed to wait on stack dump output.)\n"); + Exit(1, kFALSE); + } else { + Exit(0, kFALSE); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +/// The new thread in StackTraceForkThread() is forked to run this function +/// to print out stack trace. + +int TUnixSigHandling::StackTraceExecScript(void * /*arg*/) +{ + char *const *argv = GetStackArgv(); +#ifdef __linux__ + syscall(SYS_execve, "/bin/sh", argv, __environ); +#else + execv("/bin/sh", argv); +#endif + Exit(0, kFALSE); + return 0; +} diff --git a/core/unix/src/TUnixSystem.cxx b/core/unix/src/TUnixSystem.cxx index a0963d1ed71f9..f06502e4fe612 100644 --- a/core/unix/src/TUnixSystem.cxx +++ b/core/unix/src/TUnixSystem.cxx @@ -352,53 +352,42 @@ const char *kServerPath = "/tmp"; const char *kProtocolName = "tcp"; //------------------- Unix TFdSet ---------------------------------------------- -#ifndef HOWMANY -# define HOWMANY(x, y) (((x)+((y)-1))/(y)) -#endif -const Int_t kNFDBITS = (sizeof(Long_t) * 8); // 8 bits per byte -#ifdef FD_SETSIZE -const Int_t kFDSETSIZE = FD_SETSIZE; // Linux = 1024 file descriptors -#else -const Int_t kFDSETSIZE = 256; // upto 256 file descriptors -#endif +TFdSet::TFdSet() { memset(fds_bits, 0, sizeof(fds_bits)); } +TFdSet::TFdSet(const TFdSet &org) { memcpy(fds_bits, org.fds_bits, sizeof(org.fds_bits)); } -class TFdSet { -private: - ULong_t fds_bits[HOWMANY(kFDSETSIZE, kNFDBITS)]; -public: - TFdSet() { memset(fds_bits, 0, sizeof(fds_bits)); } - TFdSet(const TFdSet &org) { memcpy(fds_bits, org.fds_bits, sizeof(org.fds_bits)); } - TFdSet &operator=(const TFdSet &rhs) { if (this != &rhs) { memcpy(fds_bits, rhs.fds_bits, sizeof(rhs.fds_bits));} return *this; } - void Zero() { memset(fds_bits, 0, sizeof(fds_bits)); } - void Set(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - fds_bits[n/kNFDBITS] |= (1UL << (n % kNFDBITS)); - } else { - ::Fatal("TFdSet::Set","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - } +void TFdSet::Zero() { memset(fds_bits, 0, sizeof(fds_bits)); } + +void TFdSet::Set(Int_t n) +{ + if (n >= 0 && n < kFDSETSIZE) { + fds_bits[n/kNFDBITS] |= (1UL << (n % kNFDBITS)); + } else { + ::Fatal("TFdSet::Set","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); } - void Clr(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - fds_bits[n/kNFDBITS] &= ~(1UL << (n % kNFDBITS)); - } else { - ::Fatal("TFdSet::Clr","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - } +} + +void TFdSet::Clr(Int_t n) +{ + if (n >= 0 && n < kFDSETSIZE) { + fds_bits[n/kNFDBITS] &= ~(1UL << (n % kNFDBITS)); + } else { + ::Fatal("TFdSet::Clr","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); } - Int_t IsSet(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - return (fds_bits[n/kNFDBITS] & (1UL << (n % kNFDBITS))) != 0; - } else { - ::Fatal("TFdSet::IsSet","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - return 0; - } +} + +Int_t TFdSet::IsSet(Int_t n) +{ + if (n >= 0 && n < kFDSETSIZE) { + return (fds_bits[n/kNFDBITS] & (1UL << (n % kNFDBITS))) != 0; + } else { + ::Fatal("TFdSet::IsSet","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); + return 0; } - ULong_t *GetBits() { return (ULong_t *)fds_bits; } -}; +} + +ULong_t* TFdSet::GetBits() { return (ULong_t *)fds_bits; } //////////////////////////////////////////////////////////////////////////////// From 56b6049b6c7b0d6a21b96042df1863a0c6c119f8 Mon Sep 17 00:00:00 2001 From: zzxuanyuan Date: Thu, 10 Mar 2016 18:23:12 -0600 Subject: [PATCH 3/7] Change auxiliary functions in TUnixSigHandling to gSystem functions --- core/unix/inc/TUnixSigHandling.h | 3 -- core/unix/src/TUnixSigHandling.cxx | 55 +++++------------------------- 2 files changed, 9 insertions(+), 49 deletions(-) diff --git a/core/unix/inc/TUnixSigHandling.h b/core/unix/inc/TUnixSigHandling.h index 8d446bc1faac0..76dc09ae115cd 100644 --- a/core/unix/inc/TUnixSigHandling.h +++ b/core/unix/inc/TUnixSigHandling.h @@ -58,9 +58,6 @@ class TUnixSigHandling : public TSigHandling { virtual ~TUnixSigHandling(); //---- Misc ------------------------------------------------- - static const char *Getenv(const char *name); - static int GetPid(); - static void Exit(int code, Bool_t mode = kTRUE); void Init(); //---- Handling of system events ---------------------------- diff --git a/core/unix/src/TUnixSigHandling.cxx b/core/unix/src/TUnixSigHandling.cxx index c4e00421733d8..82493f88c0c94 100644 --- a/core/unix/src/TUnixSigHandling.cxx +++ b/core/unix/src/TUnixSigHandling.cxx @@ -299,7 +299,7 @@ void TUnixSigHandling::Init() #endif #ifndef ROOTPREFIX - gRootDir = Getenv("ROOTSYS"); + gRootDir = gSystem->Getenv("ROOTSYS"); if (gRootDir == 0) gRootDir= "/usr/local/root"; #else @@ -331,43 +331,6 @@ void TUnixSigHandling::Init() StackTraceHelperInit(); } -//---- Misc -------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// Get environment variable. - -const char *TUnixSigHandling::Getenv(const char *name) -{ - return ::getenv(name); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Get process id. - -int TUnixSigHandling::GetPid() -{ - return ::getpid(); -} - -//////////////////////////////////////////////////////////////////////////////// -///// Exit the application. - -void TUnixSigHandling::Exit(int code, Bool_t mode) -{ - // Insures that the files and sockets are closed before any library is unloaded - // and before emptying CINT. - if (gROOT) { - gROOT->EndOfProcessCleanups(); - } else if (gInterpreter) { - gInterpreter->ResetGlobals(); - } - - if (mode) - ::exit(code); - else - ::_exit(code); -} - //////////////////////////////////////////////////////////////////////////////// /// Add a signal handler to list of system signal handlers. Only adds /// the handler if it is not already in the list of signal handlers. @@ -575,7 +538,7 @@ void TUnixSigHandling::DispatchSignals(ESignals sig) else //map to the real signal code + set the //high order bit to indicate a signal (?) - Exit(gSignalMap[sig].fCode + 0x80); + gSystem->Exit(gSignalMap[sig].fCode + 0x80); break; case kSigSystem: case kSigPipe: @@ -767,7 +730,7 @@ void TUnixSigHandling::StackTrace() void TUnixSigHandling::StackTraceHelperInit() { - if(snprintf(gStackTraceHelper.fPidNum, kStringLength-1, "%d", GetPid()) >= kStringLength) { + if(snprintf(gStackTraceHelper.fPidNum, kStringLength-1, "%d", gSystem->GetPid()) >= kStringLength) { SignalSafeErrWrite("Unable to pre-allocate process id information"); return; } @@ -810,7 +773,7 @@ void TUnixSigHandling::StackTraceMonitorThread() SignalSafeErrWrite("\n\nTraceback helper thread failed to read from parent: "); SignalSafeErrWrite(strerror(-result)); SignalSafeErrWrite("\n"); - Exit(1, kFALSE); + gSystem->Exit(1, kFALSE); } if (buf[0] == '1') { UnixSetDefaultSignals(); @@ -829,7 +792,7 @@ void TUnixSigHandling::StackTraceMonitorThread() SignalSafeErrWrite("\n\nTraceback helper thread got unknown command from parent: "); SignalSafeErrWrite(buf); SignalSafeErrWrite("\n"); - Exit(1, kFALSE); + gSystem->Exit(1, kFALSE); } } return; @@ -871,7 +834,7 @@ void TUnixSigHandling::StackTraceForkThread() #else fork(); if (childStackPtr) {} // Suppress 'unused variable' warning on non-Linux - if (pid == 0) { StackTraceExecScript(nullptr); Exit(0, kFALSE); } + if (pid == 0) { StackTraceExecScript(nullptr); gSystem->Exit(0, kFALSE); } #endif if (pid == -1) { SignalSafeErrWrite("(Attempt to perform stack dump failed.)\n"); @@ -879,9 +842,9 @@ void TUnixSigHandling::StackTraceForkThread() int status; if (waitpid(pid, &status, 0) == -1) { SignalSafeErrWrite("(Failed to wait on stack dump output.)\n"); - Exit(1, kFALSE); + gSystem->Exit(1, kFALSE); } else { - Exit(0, kFALSE); + gSystem->Exit(0, kFALSE); } } } @@ -898,6 +861,6 @@ int TUnixSigHandling::StackTraceExecScript(void * /*arg*/) #else execv("/bin/sh", argv); #endif - Exit(0, kFALSE); + gSystem->Exit(0, kFALSE); return 0; } From 1fcbcd349fc52ee9216d4f43c82bbdff11855e54 Mon Sep 17 00:00:00 2001 From: zzxuanyuan Date: Fri, 11 Mar 2016 00:20:15 -0600 Subject: [PATCH 4/7] Changed Author and removed type cast and includes handling kSigFloatingException --- core/base/inc/TSigHandling.h | 1 + core/base/src/TSigHandling.cxx | 9 +++++++++ core/base/src/TSystem.cxx | 3 +-- core/unix/inc/TUnixSigHandling.h | 2 +- core/unix/src/TUnixSigHandling.cxx | 31 +++++++++++++++--------------- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/base/inc/TSigHandling.h b/core/base/inc/TSigHandling.h index 3a7bcdd5e52b8..7151e54d6e00d 100644 --- a/core/base/inc/TSigHandling.h +++ b/core/base/inc/TSigHandling.h @@ -77,6 +77,7 @@ class TSigHandling : public TNamed { //---- Handling of system signals virtual Bool_t HaveTrappedSignal(Bool_t pendingOnly); + virtual void DispatchSignals(ESignals sig); virtual void AddSignalHandler(TSignalHandler *sh); virtual TSignalHandler *RemoveSignalHandler(TSignalHandler *sh); virtual void ResetSignal(ESignals sig, Bool_t reset = kTRUE); diff --git a/core/base/src/TSigHandling.cxx b/core/base/src/TSigHandling.cxx index e0ea1cafd09be..040e077e98295 100644 --- a/core/base/src/TSigHandling.cxx +++ b/core/base/src/TSigHandling.cxx @@ -92,6 +92,15 @@ Bool_t TSigHandling::HaveTrappedSignal(Bool_t) return kFALSE; } +//////////////////////////////////////////////////////////////////////////////// +/// Dispatch signals. + +void TSigHandling::DispatchSignals(ESignals /*sig*/) +{ + AbstractMethod("DispatchSignals"); +} + + //////////////////////////////////////////////////////////////////////////////// /// Add a signal handler to list of system signal handlers. Only adds /// the handler if it is not already in the list of signal handlers. diff --git a/core/base/src/TSystem.cxx b/core/base/src/TSystem.cxx index 0ba18e6025d3e..ef508570ff1d7 100644 --- a/core/base/src/TSystem.cxx +++ b/core/base/src/TSystem.cxx @@ -537,7 +537,7 @@ void TSystem::AddSignalHandler(TSignalHandler *h) TSignalHandler *TSystem::RemoveSignalHandler(TSignalHandler *h) { - return (TSignalHandler *)gSigHandling->RemoveSignalHandler(h); + return gSigHandling->RemoveSignalHandler(h); } //////////////////////////////////////////////////////////////////////////////// @@ -738,7 +738,6 @@ void TSystem::StackTrace() AbstractMethod("StackTrace"); } - //---- Directories ------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// diff --git a/core/unix/inc/TUnixSigHandling.h b/core/unix/inc/TUnixSigHandling.h index 76dc09ae115cd..084112b6aa296 100644 --- a/core/unix/inc/TUnixSigHandling.h +++ b/core/unix/inc/TUnixSigHandling.h @@ -1,5 +1,5 @@ // @(#)root/unix:$Id$ -// Author: Fons Rademakers 15/09/95 +// Author: Zhe Zhang 10/03/16 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * diff --git a/core/unix/src/TUnixSigHandling.cxx b/core/unix/src/TUnixSigHandling.cxx index 82493f88c0c94..4865f116138e9 100644 --- a/core/unix/src/TUnixSigHandling.cxx +++ b/core/unix/src/TUnixSigHandling.cxx @@ -1,5 +1,5 @@ // @(#)root/unix:$Id: 887c618d89c4ed436e4034fc133f468fecad651b $ -// Author: Fons Rademakers 15/09/95 +// Author: Zhe Zhang 10/03/16 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * @@ -133,7 +133,7 @@ static void SetRootSys() static void SigHandler(ESignals sig) { if (gSigHandling) - ((TUnixSigHandling*)gSigHandling)->DispatchSignals(sig); + gSigHandling->DispatchSignals(sig); } //////////////////////////////////////////////////////////////////////////////// @@ -515,10 +515,10 @@ void TUnixSigHandling::DispatchSignals(ESignals sig) { switch (sig) { case kSigAlarm: -// DispatchTimers(kFALSE); +// gSystem->DispatchTimers(kFALSE); break; case kSigChild: -// CheckChilds(); +// gSystem->CheckChilds(); break; case kSigBus: SignalSafeErrWrite("\n\nA fatal system signal has occurred: bus error"); @@ -530,19 +530,13 @@ void TUnixSigHandling::DispatchSignals(ESignals sig) SignalSafeErrWrite("\n\nA fatal system signal has occurred: illegal instruction error"); break; case kSigFloatingException: - Break("TUnixSigHandling::DispatchSignals", "%s", UnixSigname(sig)); - StackTrace(); - if (gApplication) - //sig is ESignal, should it be mapped to the correct signal number? - gApplication->HandleException(sig); - else - //map to the real signal code + set the - //high order bit to indicate a signal (?) - gSystem->Exit(gSignalMap[sig].fCode + 0x80); + SignalSafeErrWrite("\n\nA fatal system signal has occurred: floating exception error"); break; case kSigSystem: + SignalSafeErrWrite("\n\nA fatal system signal has occurred: system error"); + break; case kSigPipe: - Break("TUnixSigHandling::DispatchSignals", "%s", UnixSigname(sig)); + SignalSafeErrWrite("\n\nA fatal system signal has occurred: pipe error"); break; case kSigWindowChanged: Gl_windowchanged(); @@ -553,11 +547,18 @@ void TUnixSigHandling::DispatchSignals(ESignals sig) break; } - if ((sig == kSigIllegalInstruction) || (sig == kSigSegmentationViolation) || (sig == kSigBus)) + if ((sig == kSigIllegalInstruction) || (sig == kSigSegmentationViolation) || (sig == kSigBus) || (sig == kSigFloatingException)) { StackTraceTriggerThread(); signal(sig, SIG_DFL); raise(sig); + if (gApplication) + //sig is ESignal, should it be mapped to the correct signal number? + gApplication->HandleException(sig); + else + //map to the real signal code + set the + //high order bit to indicate a signal (?) + gSystem->Exit(gSignalMap[sig].fCode + 0x80, 0); } // check a-synchronous signals From 1e3296887abf8411346680a62ecf40cde0806d45 Mon Sep 17 00:00:00 2001 From: zzxuanyuan Date: Fri, 11 Mar 2016 11:56:55 -0600 Subject: [PATCH 5/7] Type casting gSystem to TUnixSystem and directly call DispatchTimers() and CheckChilds() from TUnixSystem.cxx --- core/base/inc/TSigHandling.h | 2 -- core/unix/src/TUnixSigHandling.cxx | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/base/inc/TSigHandling.h b/core/base/inc/TSigHandling.h index 7151e54d6e00d..8c539a4008cc4 100644 --- a/core/base/inc/TSigHandling.h +++ b/core/base/inc/TSigHandling.h @@ -22,14 +22,12 @@ // // ////////////////////////////////////////////////////////////////////////// -#ifndef __CINT__ #include #include #include #ifndef WIN32 #include #endif -#endif #ifndef ROOT_TNamed #include "TNamed.h" diff --git a/core/unix/src/TUnixSigHandling.cxx b/core/unix/src/TUnixSigHandling.cxx index 4865f116138e9..2411c1659dae3 100644 --- a/core/unix/src/TUnixSigHandling.cxx +++ b/core/unix/src/TUnixSigHandling.cxx @@ -515,10 +515,10 @@ void TUnixSigHandling::DispatchSignals(ESignals sig) { switch (sig) { case kSigAlarm: -// gSystem->DispatchTimers(kFALSE); + ((TUnixSystem *)gSystem)->DispatchTimers(kFALSE); break; case kSigChild: -// gSystem->CheckChilds(); + ((TUnixSystem *)gSystem)->CheckChilds(); break; case kSigBus: SignalSafeErrWrite("\n\nA fatal system signal has occurred: bus error"); From 8da31872eb65fbf7db0f9dc8307a6527cc348994 Mon Sep 17 00:00:00 2001 From: Brian Bockelman Date: Sun, 11 Sep 2016 22:01:47 -0500 Subject: [PATCH 6/7] Fixup cmake glob that breaks newer versions of cmake. --- core/unix/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/unix/CMakeLists.txt b/core/unix/CMakeLists.txt index aa0f9bfedca17..decf15f71fba5 100644 --- a/core/unix/CMakeLists.txt +++ b/core/unix/CMakeLists.txt @@ -4,7 +4,7 @@ ROOT_GLOB_SOURCES(sources ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cxx) -set(Unix_dict_headers ${CMAKE_CURRENT_SOURCE_DIR}/inc/T*.h PARENT_SCOPE) +set(Unix_dict_headers ${CMAKE_CURRENT_SOURCE_DIR}/inc/TUnixSigHandling.h ${CMAKE_CURRENT_SOURCE_DIR}/inc/TUnixSystem.h PARENT_SCOPE) include_directories(${CMAKE_SOURCE_DIR}/net/net/inc) ROOT_OBJECT_LIBRARY(Unix ${sources}) From 022b5030ec27439ed3fb062387f93abb5ef073be Mon Sep 17 00:00:00 2001 From: Philippe Canal Date: Mon, 20 Jun 2016 17:15:09 -0500 Subject: [PATCH 7/7] Fix macosx compilation --- core/macosx/src/TMacOSXSystem.mm | 62 +----------------------------- core/unix/src/TUnixSigHandling.cxx | 36 ++++++----------- core/unix/src/TUnixSystem.cxx | 4 +- 3 files changed, 15 insertions(+), 87 deletions(-) diff --git a/core/macosx/src/TMacOSXSystem.mm b/core/macosx/src/TMacOSXSystem.mm index d297acd2429e1..8238c2b680c99 100644 --- a/core/macosx/src/TMacOSXSystem.mm +++ b/core/macosx/src/TMacOSXSystem.mm @@ -57,61 +57,6 @@ - (void) stopRun //Fortunately, this does not violate ODR, but still UGLY. // -//------------------- Unix TFdSet ---------------------------------------------- -#ifndef HOWMANY -# define HOWMANY(x, y) (((x)+((y)-1))/(y)) -#endif - -const Int_t kNFDBITS = (sizeof(Long_t) * 8); // 8 bits per byte -#ifdef FD_SETSIZE -const Int_t kFDSETSIZE = FD_SETSIZE; // Linux = 1024 file descriptors -#else -const Int_t kFDSETSIZE = 256; // upto 256 file descriptors -#endif - - -class TFdSet { -private: - ULong_t fds_bits[HOWMANY(kFDSETSIZE, kNFDBITS)]; -public: - TFdSet() { memset(fds_bits, 0, sizeof(fds_bits)); } - TFdSet(const TFdSet &org) { memcpy(fds_bits, org.fds_bits, sizeof(org.fds_bits)); } - TFdSet &operator=(const TFdSet &rhs) - { - if (this != &rhs) { - memcpy(fds_bits, rhs.fds_bits, sizeof(rhs.fds_bits)); - } - return *this; - } - void Zero() { memset(fds_bits, 0, sizeof(fds_bits)); } - void Set(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - fds_bits[n/kNFDBITS] |= (1UL << (n % kNFDBITS)); - } else { - ::Fatal("TFdSet::Set","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - } - } - void Clr(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - fds_bits[n/kNFDBITS] &= ~(1UL << (n % kNFDBITS)); - } else { - ::Fatal("TFdSet::Clr","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - } - } - Int_t IsSet(Int_t n) - { - if (n >= 0 && n < kFDSETSIZE) { - return (fds_bits[n/kNFDBITS] & (1UL << (n % kNFDBITS))) != 0; - } else { - ::Fatal("TFdSet::IsSet","fd (%d) out of range [0..%d]", n, kFDSETSIZE-1); - return 0; - } - } - ULong_t *GetBits() { return (ULong_t *)fds_bits; } -}; - namespace ROOT { namespace MacOSX { namespace Detail { @@ -370,12 +315,7 @@ void TMacOSXSystem_WriteCallback(CFFileDescriptorRef fdref, CFOptionFlags /*call return; // check synchronous signals - if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) - if (CheckSignals(kTRUE)) - if (!pendingOnly) return; - - fSigcnt = 0; - fSignals->Zero(); + if (HaveTrappedSignal(pendingOnly)) return; // check synchronous timers Long_t nextto = 0; diff --git a/core/unix/src/TUnixSigHandling.cxx b/core/unix/src/TUnixSigHandling.cxx index 2411c1659dae3..4d6a66720949d 100644 --- a/core/unix/src/TUnixSigHandling.cxx +++ b/core/unix/src/TUnixSigHandling.cxx @@ -95,12 +95,6 @@ # include #endif -#ifdef HAVE_BACKTRACE_SYMBOLS_FD - // The maximum stack trace depth for systems where we request the - // stack depth separately (currently glibc-based systems). - static const int kMAX_BACKTRACE_DEPTH = 128; -#endif - class TFdSet; #if defined(HAVE_DLADDR) && !defined(R__MACOSX) @@ -290,22 +284,6 @@ void TUnixSigHandling::Init() UnixSignal(kSigFloatingException, SigHandler); UnixSignal(kSigWindowChanged, SigHandler); -#if defined(R__MACOSX) - // trap loading of all dylibs to register dylib name, - // sets also ROOTSYS if built without ROOTPREFIX - _dyld_register_func_for_add_image(DylibAdded); -#elif defined(HAVE_DLADDR) - SetRootSys(); -#endif - -#ifndef ROOTPREFIX - gRootDir = gSystem->Getenv("ROOTSYS"); - if (gRootDir == 0) - gRootDir= "/usr/local/root"; -#else - gRootDir = ROOTPREFIX; -#endif - if(snprintf(gStackTraceHelper.fShellExec, kStringLength-1, "/bin/sh") >= kStringLength) { SignalSafeErrWrite("Unable to pre-allocate shell command path"); return; @@ -743,11 +721,21 @@ void TUnixSigHandling::StackTraceHelperInit() close(gStackTraceHelper.fParentToChild[1]); gStackTraceHelper.fParentToChild[0] = -1; gStackTraceHelper.fParentToChild[1] = -1; - if (-1 == pipe2(gStackTraceHelper.fChildToParent, O_CLOEXEC)) { +#ifdef R__MACOSX + if (-1 == pipe(gStackTraceHelper.fChildToParent)) +#else + if (-1 == pipe2(gStackTraceHelper.fChildToParent, O_CLOEXEC)) +#endif + { fprintf(stdout, "pipe gStackTraceHelper.fChildToParent failed\n"); return; } - if (-1 == pipe2(gStackTraceHelper.fParentToChild, O_CLOEXEC)){ +#ifdef R__MACOSX + if (-1 == pipe(gStackTraceHelper.fParentToChild)) +#else + if (-1 == pipe2(gStackTraceHelper.fParentToChild, O_CLOEXEC)) +#endif + { close(gStackTraceHelper.fChildToParent[0]); close(gStackTraceHelper.fChildToParent[1]); gStackTraceHelper.fChildToParent[0] = -1; gStackTraceHelper.fChildToParent[1] = -1; fprintf(stdout, "pipe parentToChild failed\n"); diff --git a/core/unix/src/TUnixSystem.cxx b/core/unix/src/TUnixSystem.cxx index f06502e4fe612..b9a1fb7007bee 100644 --- a/core/unix/src/TUnixSystem.cxx +++ b/core/unix/src/TUnixSystem.cxx @@ -571,8 +571,6 @@ Bool_t TUnixSystem::Init() fWriteready = new TFdSet; //--- install default handlers - gSigHandling->Init(); - #if defined(R__MACOSX) // trap loading of all dylibs to register dylib name, // sets also ROOTSYS if built without ROOTPREFIX @@ -589,6 +587,8 @@ Bool_t TUnixSystem::Init() gRootDir = ROOTPREFIX; #endif + gSigHandling->Init(); + return kFALSE; }