jexcept.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #ifndef __JEXCEPT__
  15. #define __JEXCEPT__
  16. #include "jexpdef.hpp"
  17. #include "jiface.hpp"
  18. #include "jlib.hpp"
  19. #include "errno.h"
  20. // When changing this enum, be sure to update (a) the string functions, and (b) NUM value in jlog.hpp
  21. typedef enum
  22. {
  23. MSGAUD_unknown = 0x00,
  24. MSGAUD_operator = 0x01,
  25. MSGAUD_user = 0x02,
  26. MSGAUD_monitor = 0x04,
  27. MSGAUD_performance = 0x08,
  28. MSGAUD_internal = 0x10,
  29. MSGAUD_programmer = 0x20,
  30. MSGAUD_legacy = 0x40,
  31. MSGAUD_audit = 0x80,
  32. MSGAUD_all = 0xFF
  33. } MessageAudience;
  34. jlib_decl const char* SerializeMessageAudience(MessageAudience ma);
  35. jlib_decl MessageAudience DeserializeMessageAudience(const char* text);
  36. interface jlib_thrown_decl IException : public IInterface
  37. {
  38. virtual int errorCode() const = 0;
  39. virtual StringBuffer & errorMessage(StringBuffer &msg) const = 0;
  40. virtual MessageAudience errorAudience() const = 0;
  41. };
  42. //the following interface to be thrown when a user command explicitly calls for a failure
  43. interface jlib_thrown_decl IUserException : public IException
  44. {
  45. };
  46. //the following interface defines a collection of exceptions
  47. //
  48. interface jlib_thrown_decl IMultiException : extends IException
  49. {
  50. //convenience methods for handling this as an array
  51. virtual aindex_t ordinality() const = 0;
  52. virtual IException& item(aindex_t pos) const = 0;
  53. virtual const char* source() const = 0;
  54. //for complete control...
  55. virtual IArrayOf<IException>& getArray()= 0;
  56. //add another exception
  57. virtual void append(IException& e) = 0;
  58. virtual void append(IMultiException& e) = 0;
  59. virtual StringBuffer& serialize(StringBuffer& ret, unsigned indent = 0, bool simplified=false, bool root=true) const = 0;
  60. virtual void deserialize(const char* xml) = 0; //throws IException on failure!
  61. //the following methods override those in IIException
  62. //
  63. virtual int errorCode() const = 0;
  64. virtual StringBuffer& errorMessage(StringBuffer &msg) const = 0;
  65. virtual MessageAudience errorAudience() const = 0;
  66. };
  67. IMultiException jlib_decl *MakeMultiException(const char* source = NULL);
  68. interface IExceptionHandler
  69. {
  70. virtual bool fireException(IException *e) = 0;
  71. };
  72. IException jlib_decl *MakeStringException(int code,const char *why, ...) __attribute__((format(printf, 2, 3)));
  73. IException jlib_decl *MakeStringExceptionVA(int code,const char *why, va_list args);
  74. IException jlib_decl *MakeStringExceptionDirect(int code,const char *why);
  75. IException jlib_decl *MakeStringException(MessageAudience aud,int code,const char *why, ...) __attribute__((format(printf, 3, 4)));
  76. IException jlib_decl *MakeStringExceptionVA(MessageAudience aud,int code,const char *why, va_list args);
  77. IException jlib_decl *MakeStringExceptionDirect(MessageAudience aud,int code,const char *why);
  78. void jlib_decl ThrowStringException(int code,const char *format, ...) __attribute__((format(printf, 2, 3)));
  79. interface jlib_thrown_decl IOSException: extends IException{};
  80. IOSException jlib_decl *MakeOsException(int code);
  81. IOSException jlib_decl *MakeOsException(int code, const char *msg, ...) __attribute__((format(printf, 2, 3)));
  82. #define DISK_FULL_EXCEPTION_CODE ENOSPC
  83. interface jlib_thrown_decl IErrnoException: extends IException{};
  84. IErrnoException jlib_decl *MakeErrnoException(int errn=-1);
  85. IErrnoException jlib_decl *MakeErrnoException(int errn, const char *why, ...) __attribute__((format(printf, 2, 3)));
  86. IErrnoException jlib_decl *MakeErrnoException(const char *why, ...) __attribute__((format(printf, 1, 2)));
  87. IErrnoException jlib_decl *MakeErrnoException(MessageAudience aud,int errn=-1);
  88. IErrnoException jlib_decl *MakeErrnoException(MessageAudience aud,int errn, const char *why, ...) __attribute__((format(printf, 3, 4)));
  89. IErrnoException jlib_decl *MakeErrnoException(MessageAudience aud,const char *why, ...) __attribute__((format(printf, 2, 3)));
  90. void jlib_decl pexception(const char *msg,IException *e); // like perror except for exceptions
  91. jlib_decl StringBuffer & formatSystemError(StringBuffer & out, unsigned errcode);
  92. void userBreakpoint();
  93. interface jlib_thrown_decl ISEH_Exception : extends IException
  94. {
  95. };
  96. interface jlib_thrown_decl IOutOfMemException: extends IException
  97. {
  98. };
  99. void jlib_decl EnableSEHtoExceptionMapping(); // return value can be used to disable
  100. void jlib_decl DisableSEHtoExceptionMapping();
  101. // NB only enables for current thread or threads started after call
  102. // requires /EHa option to be set in VC++ options (after /GX)
  103. void jlib_decl *setSEHtoExceptionHandler(IExceptionHandler *handler); // sets handler and return old value
  104. void jlib_decl setTerminateOnSEHInSystemDLLs(bool set=true);
  105. void jlib_decl setTerminateOnSEH(bool set=true);
  106. #define throwUnexpected() throw MakeStringException(9999, "Internal Error at %s(%d)", __FILE__, __LINE__)
  107. #define assertThrow(x) assertex(x)
  108. #define UNIMPLEMENTED throw MakeStringException(-1, "UNIMPLEMENTED feature at %s(%d)", __FILE__, __LINE__)
  109. #define UNIMPLEMENTED_X(reason) throw MakeStringException(-1, "UNIMPLEMENTED '" reason "' at %s(%d)", __FILE__, __LINE__)
  110. #define UNIMPLEMENTED_XY(a,b) throw MakeStringException(-1, "UNIMPLEMENTED " a " %s at %s(%d)", b, __FILE__, __LINE__)
  111. IException jlib_decl * deserializeException(MemoryBuffer & in);
  112. void jlib_decl serializeException(IException * e, MemoryBuffer & out);
  113. void jlib_decl PrintStackReport();
  114. #ifdef _DEBUG
  115. #define RELEASE_CATCH_ALL int*********
  116. #else
  117. #define RELEASE_CATCH_ALL ...
  118. #endif
  119. //These are used in several places to wrap error reporting, to keep error numbers+text together. E.g.,
  120. //#define XYZfail 99 #define XXZfail_Text "Failed" throwError(XYZfail)
  121. #define throwError(x) ThrowStringException(x, (x ## _Text))
  122. #define throwError1(x,a) ThrowStringException(x, (x ## _Text), a)
  123. #define throwError2(x,a,b) ThrowStringException(x, (x ## _Text), a, b)
  124. #define throwError3(x,a,b,c) ThrowStringException(x, (x ## _Text), a, b, c)
  125. #define throwError4(x,a,b,c,d) ThrowStringException(x, (x ## _Text), a, b, c, d)
  126. #ifndef _WIN32
  127. #define SIGNAL_TO_EXCEPTION
  128. #endif
  129. #ifdef SIGNAL_TO_EXCEPTION
  130. #include <setjmp.h>
  131. /******************************************************************************
  132. * !! NOTE: the following only works for single threaded programs at present !!
  133. *
  134. * Visual C++ intercepts hardware traps like segmentation violation,
  135. * floating point exception as C++ exceptions in catch(...).
  136. * Unfortunately, this does not work in Linux and causes program to
  137. * trap. This class attempts to implement Visual C++ functionality
  138. * using signal handlers, setjmp/longjmp and works in conjunction
  139. * with the TRY, CATCH, CATCH_ALL, END_CATCH macros as defined below.
  140. *
  141. * The first invocation of constructor sets up a signal handler for
  142. * SIGSEGV, SIGILL, SIGFPE, SIGPIPE and SIGSYS. TRY macro instantiates
  143. * an object of this class on stack, which saves the current value
  144. * of static class member jmp_buf, s_jmpbuf, in data member m_old_jmpbuf
  145. * with the intention to restore it upon destruction. The TRY macro
  146. * also invokes setjmp to save the CPU state in the static member. If
  147. * an exception occurs within the TRY block, the signal handler is invoked
  148. * and simply invokes longjmp on the static jmpbuf oblivious to the
  149. * current context. It so happens that this static jmpbuf member always
  150. * points to the current TRY block. The program control resumes at the
  151. * setjmp call, that now returns signal number due to the longjmp call
  152. * from the signal handler. This results in a C++ exception to be thrown
  153. * which gets intercepted in the corresponding catch block.
  154. */
  155. class jlib_thrown_decl SignalToException
  156. {
  157. public:
  158. SignalToException();
  159. virtual ~SignalToException();
  160. static void processSetJmpResult(int res);
  161. static jmp_buf s_jmpbuf;
  162. private:
  163. static void UnixTrapHandler(int sig);
  164. static void setUnixTrapHandler();
  165. static bool s_bUnixTrapHandlerSet;
  166. jmp_buf m_old_jmpbuf;
  167. };
  168. #define TRY \
  169. try \
  170. {\
  171. SignalToException _signalToException;\
  172. /* note that setjmp needs to be invoked in this context \
  173. * or else it traps on longjmp from signal handler */\
  174. SignalToException::processSetJmpResult( setjmp(SignalToException::s_jmpbuf) );
  175. #define CATCH } catch
  176. #define AND_CATCH catch
  177. #define END_CATCH /*optional*/
  178. /* use these macros as follows:
  179. *
  180. * TRY {
  181. * }
  182. * CATCH(exception type) {
  183. * }
  184. * AND_CATCH(exception type) {
  185. * }
  186. * ...
  187. * END_CATCH
  188. *
  189. */
  190. #else //SIGNAL_TO_EXCEPTION defined
  191. #ifndef __AFX_H__
  192. #define TRY try
  193. #define CATCH catch
  194. #define AND_CATCH catch
  195. #define END_CATCH /*optional*/
  196. #endif
  197. #endif //SIGNAL_TO_EXCEPTION not defined
  198. #endif