jexcept.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include <algorithm>
  15. #include "jexcept.hpp"
  16. #include <assert.h>
  17. #include <stdio.h>
  18. #include <stdarg.h>
  19. #include <errno.h>
  20. #include "jptree.hpp"
  21. #ifdef _WIN32
  22. #include "psapi.h"
  23. #include <eh.h>
  24. #elif defined (__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
  25. #include <sys/wait.h>
  26. #include <sys/types.h>
  27. #include <stddef.h>
  28. #include <errno.h>
  29. #ifdef __linux__
  30. #include <execinfo.h> // comment out if not present
  31. #endif
  32. #ifdef __APPLE__
  33. #ifndef _XOPEN_SOURCE
  34. #define _XOPEN_SOURCE
  35. #endif
  36. #include <ucontext.h>
  37. #endif
  38. #endif
  39. //#define NOSEH
  40. #define NO_LINUX_SEH
  41. #define EXTENDED_EXCEPTION_TRACE
  42. #ifdef EXTENDED_EXCEPTION_TRACE
  43. #include "jmisc.hpp"
  44. #define LINUX_SIGNAL_EXCEPTION
  45. #endif
  46. class jlib_thrown_decl StringException: public CInterface, public IException
  47. {
  48. public:
  49. IMPLEMENT_IINTERFACE;
  50. StringException(int code, const char *str, MessageAudience aud = MSGAUD_user) : errcode(code), msg(str), audience(aud) {};
  51. int errorCode() const { return errcode; }
  52. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  53. MessageAudience errorAudience() const { return audience; }
  54. protected:
  55. int errcode;
  56. StringAttr msg;
  57. MessageAudience audience;
  58. };
  59. IException *MakeStringExceptionVA(int code, const char *format, va_list args)
  60. {
  61. StringBuffer eStr;
  62. eStr.limited_valist_appendf(1024, format, args);
  63. return new StringException(code, eStr.str());
  64. }
  65. IException *MakeStringException(int code,const char *format, ...)
  66. {
  67. va_list args;
  68. va_start(args, format);
  69. IException *ret = MakeStringExceptionVA(code, format, args);
  70. va_end(args);
  71. return ret;
  72. }
  73. IException jlib_decl *MakeStringExceptionDirect(int code,const char *why)
  74. {
  75. return new StringException(code,why);
  76. }
  77. IException *MakeStringExceptionVA(MessageAudience aud, int code, const char *format, va_list args)
  78. {
  79. StringBuffer eStr;
  80. eStr.limited_valist_appendf(1024, format, args);
  81. return new StringException(code, eStr.str(), aud);
  82. }
  83. IException *MakeStringException(MessageAudience aud, int code, const char *format, ...)
  84. {
  85. va_list args;
  86. va_start(args, format);
  87. IException *ret = MakeStringExceptionVA(aud, code, format, args);
  88. va_end(args);
  89. return ret;
  90. }
  91. IException jlib_decl *MakeStringExceptionDirect(MessageAudience aud,int code,const char *why)
  92. {
  93. return new StringException(code,why,aud);
  94. }
  95. void jlib_decl ThrowStringException(int code,const char *format, ...)
  96. {
  97. va_list args;
  98. va_start(args, format);
  99. IException *ret = MakeStringExceptionVA(code, format, args);
  100. va_end(args);
  101. throw ret;
  102. }
  103. class jlib_thrown_decl OsException: public CInterface, public IOSException
  104. {
  105. public:
  106. IMPLEMENT_IINTERFACE;
  107. OsException(int code) : errcode(code) {};
  108. OsException(int code, const char *_msg) : msg(_msg), errcode(code) {};
  109. ~OsException() {}
  110. int errorCode() const { return errcode; }
  111. StringBuffer & errorMessage(StringBuffer &str) const
  112. {
  113. if (msg)
  114. str.append(msg).append(", ");
  115. formatSystemError(str, errcode);
  116. return str;
  117. }
  118. MessageAudience errorAudience() const { return MSGAUD_user; }
  119. protected:
  120. StringAttr msg;
  121. int errcode;
  122. };
  123. IOSException *MakeOsException(int code)
  124. {
  125. return new OsException(code);
  126. }
  127. IOSException *MakeOsException(int code, const char *msg, ...)
  128. {
  129. StringBuffer eStr;
  130. va_list args;
  131. va_start(args, msg);
  132. eStr.limited_valist_appendf(1024, msg, args);
  133. va_end(args);
  134. return new OsException(code, eStr.str());
  135. }
  136. class jlib_thrown_decl ErrnoException: public CInterface, public IErrnoException
  137. {
  138. public:
  139. IMPLEMENT_IINTERFACE;
  140. ErrnoException(int errn) : audience(MSGAUD_user) { errcode = errn==-1?errno:errn; }
  141. ErrnoException(int errn, const char *_msg, MessageAudience aud = MSGAUD_user) : msg(_msg), audience(aud) { errcode = errn==-1?errno:errn; }
  142. ~ErrnoException() { }
  143. int errorCode() const { return errcode; }
  144. StringBuffer & errorMessage(StringBuffer &str) const
  145. {
  146. if (msg)
  147. str.append(msg).append(", ");
  148. if (errcode==DISK_FULL_EXCEPTION_CODE)
  149. str.append("Disk full");
  150. else
  151. str.append(strerror(errcode));
  152. return str;
  153. }
  154. MessageAudience errorAudience() const { return audience; }
  155. protected:
  156. StringAttr msg;
  157. int errcode;
  158. MessageAudience audience;
  159. };
  160. IErrnoException *MakeErrnoException(int errn)
  161. {
  162. return new ErrnoException(errn);
  163. }
  164. IErrnoException *MakeErrnoException(int errn, const char *msg, ...)
  165. {
  166. StringBuffer eStr;
  167. va_list args;
  168. va_start(args, msg);
  169. eStr.limited_valist_appendf(1024, msg, args);
  170. va_end(args);
  171. return new ErrnoException(errn, eStr.str());
  172. }
  173. IErrnoException *MakeErrnoException(const char *msg, ...)
  174. {
  175. StringBuffer eStr;
  176. va_list args;
  177. va_start(args, msg);
  178. eStr.limited_valist_appendf(1024, msg, args);
  179. va_end(args);
  180. return new ErrnoException(-1, eStr.str());
  181. }
  182. IErrnoException *MakeErrnoException(MessageAudience aud, int errn)
  183. {
  184. return new ErrnoException(errn, "", aud);
  185. }
  186. IErrnoException *MakeErrnoException(MessageAudience aud, int errn, const char *msg, ...)
  187. {
  188. StringBuffer eStr;
  189. va_list args;
  190. va_start(args, msg);
  191. eStr.limited_valist_appendf(1024, msg, args);
  192. va_end(args);
  193. return new ErrnoException(errn, eStr.str(), aud);
  194. }
  195. IErrnoException *MakeErrnoException(MessageAudience aud, const char *msg, ...)
  196. {
  197. StringBuffer eStr;
  198. va_list args;
  199. va_start(args, msg);
  200. eStr.limited_valist_appendf(1024, msg, args);
  201. va_end(args);
  202. return new ErrnoException(-1, eStr.str(), aud);
  203. }
  204. const char* SerializeMessageAudience(MessageAudience ma)
  205. {
  206. const char* ret;
  207. switch(ma)
  208. {
  209. case MSGAUD_unknown: ret = "unknown"; break;
  210. case MSGAUD_operator: ret = "operator"; break;
  211. case MSGAUD_user: ret = "user"; break;
  212. case MSGAUD_monitor: ret = "monitor"; break;
  213. case MSGAUD_performance: ret = "performance"; break;
  214. case MSGAUD_internal: ret = "internal"; break;
  215. case MSGAUD_programmer: ret = "programmer"; break;
  216. case MSGAUD_legacy: ret = "legacy"; break;
  217. case MSGAUD_all: ret = "all"; break;
  218. default: ret = "unknown"; break;
  219. }
  220. return ret;
  221. }
  222. MessageAudience DeserializeMessageAudience(const char* text)
  223. {
  224. MessageAudience ma = MSGAUD_unknown;
  225. if (text && *text)
  226. {
  227. if (!strcmp(text, "operator"))
  228. ma = MSGAUD_operator;
  229. else if (!strcmp(text, "user"))
  230. ma = MSGAUD_user;
  231. else if (!strcmp(text, "monitor"))
  232. ma = MSGAUD_monitor;
  233. else if (!strcmp(text, "performance"))
  234. ma = MSGAUD_performance;
  235. else if (!strcmp(text, "internal"))
  236. ma = MSGAUD_internal;
  237. else if (!strcmp(text, "programmer"))
  238. ma = MSGAUD_programmer;
  239. else if (!strcmp(text, "legacy"))
  240. ma = MSGAUD_legacy;
  241. else if (!strcmp(text, "all"))
  242. ma = MSGAUD_all;
  243. }
  244. return ma;
  245. }
  246. class jlib_thrown_decl CMultiException : public CInterface,
  247. implements IMultiException
  248. {
  249. public:
  250. IMPLEMENT_IINTERFACE
  251. CMultiException(const char* source=NULL)
  252. {
  253. if (source)
  254. source_.append(source);
  255. }
  256. //convenience methods for handling this as an array
  257. virtual aindex_t ordinality() const
  258. {
  259. synchronized block(m_mutex);
  260. return array_.ordinality();
  261. }
  262. virtual IException& item(aindex_t pos) const
  263. {
  264. synchronized block(m_mutex);
  265. return array_.item(pos);
  266. }
  267. virtual const char* source() const
  268. {
  269. synchronized block(m_mutex);
  270. return source_.str();
  271. }
  272. //for complete control...caller is responsible for thread safety!
  273. virtual IArrayOf<IException>& getArray() { return array_; }
  274. //add another exception
  275. virtual void append(IException& e)
  276. {
  277. synchronized block(m_mutex);
  278. array_.append(e);
  279. }
  280. virtual void append(IMultiException& me)
  281. {
  282. synchronized block(m_mutex);
  283. IArrayOf<IException>& exceptions = me.getArray();
  284. const char* source = me.source();
  285. ForEachItemIn(i, exceptions)
  286. {
  287. IException& e = exceptions.item(i);
  288. if (source && *source)
  289. {
  290. StringBuffer msg;
  291. msg.appendf("[%s] ",source);
  292. e.errorMessage(msg);
  293. array_.append(*MakeStringException(e.errorAudience(), e.errorCode(), "%s", msg.str()));
  294. }
  295. else
  296. array_.append(*LINK(&e));
  297. }
  298. }
  299. StringBuffer& serialize(StringBuffer& buffer, unsigned indent = 0, bool simplified=false, bool root=true) const
  300. {
  301. synchronized block(m_mutex);
  302. if (root)
  303. buffer.append("<Exceptions>");
  304. if (!simplified)
  305. {
  306. if (indent) buffer.append("\n\t");
  307. buffer.appendf("<Source>%s</Source>", source_.str());
  308. }
  309. ForEachItemIn(i, array_)
  310. {
  311. IException& exception = array_.item(i);
  312. if (indent) buffer.append("\n\t");
  313. buffer.append("<Exception>");
  314. //tag order is important for some soap clients (i.e. Java Axis)
  315. if (indent) buffer.append("\n\t\t");
  316. buffer.appendf("<Code>%d</Code>", exception.errorCode());
  317. if (indent) buffer.append("\n\t\t");
  318. buffer.appendf("<Audience>%s</Audience>", SerializeMessageAudience( exception.errorAudience() ));
  319. if (simplified)
  320. {
  321. if (indent) buffer.append("\n\t\t");
  322. StringBuffer msg;
  323. buffer.appendf("<Source>%s</Source>", source_.str());
  324. }
  325. if (indent) buffer.append("\n\t\t");
  326. StringBuffer msg;
  327. StringBuffer encoded;
  328. encodeXML(exception.errorMessage(msg).str(), encoded);
  329. buffer.appendf("<Message>%s</Message>", encoded.str());
  330. if (indent) buffer.append("\n\t");
  331. buffer.append("</Exception>");
  332. }
  333. if (root)
  334. buffer.append("</Exceptions>");
  335. return buffer;
  336. }
  337. virtual void deserialize(const char* xml)
  338. {
  339. synchronized block(m_mutex);
  340. StringBuffer wrapper;
  341. if (strncmp(xml, "<Exceptions>", 12))
  342. xml = wrapper.appendf("<Exceptions>%s</Exceptions>", xml).str();
  343. Owned<IPropertyTree> pTree = createPTreeFromXMLString(xml);
  344. if (!pTree)
  345. throw MakeStringException(-1, "Failed to deserialize IMultiException!");
  346. Owned<IPropertyTreeIterator> i = pTree->getElements("Exception");
  347. if (pTree->hasProp("Source"))
  348. source_.clear().append( pTree->queryProp("Source"));
  349. else
  350. {
  351. if (i->first())
  352. {
  353. IPropertyTree* pNode = &i->query();
  354. source_.clear().append( pNode->queryProp("Source"));
  355. }
  356. }
  357. array_.kill();
  358. ForEach(*i)
  359. {
  360. IPropertyTree* pNode = &i->query();
  361. IException* pException =
  362. MakeStringExceptionDirect(
  363. DeserializeMessageAudience(pNode->queryProp("Audience")),
  364. pNode->getPropInt("Code", -1),
  365. pNode->queryProp("Message"));
  366. array_.append(*pException);
  367. }
  368. }
  369. //the following methods override those in IIException
  370. //
  371. virtual int errorCode() const
  372. {
  373. synchronized block(m_mutex);
  374. return ordinality() == 1 ? item(0).errorCode() : -1;
  375. }
  376. virtual StringBuffer& errorMessage(StringBuffer &msg) const
  377. {
  378. synchronized block(m_mutex);
  379. ForEachItemIn(i, array_)
  380. {
  381. IException& e = item(i);
  382. StringBuffer buf;
  383. msg.appendf("[%3d: %s] ", e.errorCode(), e.errorMessage(buf).str());
  384. }
  385. return msg;
  386. }
  387. virtual MessageAudience errorAudience() const
  388. {
  389. synchronized block(m_mutex);
  390. return ordinality() == 1 ? item(0).errorAudience() : MSGAUD_unknown;
  391. }
  392. private:
  393. CMultiException( const CMultiException& );
  394. IArrayOf<IException> array_;
  395. StringBuffer source_;
  396. mutable Mutex m_mutex;
  397. };
  398. IMultiException *MakeMultiException(const char* source/*=NULL*/)
  399. {
  400. return new CMultiException(source);
  401. }
  402. void pexception(const char *msg,IException *e)
  403. { // like perror except for exceptions
  404. StringBuffer s;
  405. fprintf(stderr,"%s : %s\n",msg,e?e->errorMessage(s).toCharArray():"NULL Exception!");
  406. }
  407. void userBreakpoint()
  408. {
  409. #ifdef _WIN32
  410. try
  411. {
  412. DebugBreak();
  413. }
  414. catch (...)
  415. {
  416. //if not debugging don't give an unhandled exception.
  417. }
  418. #endif
  419. }
  420. void RaiseAssertException(const char *assertion, const char *file, unsigned line)
  421. {
  422. PrintStackReport();
  423. StringBuffer s;
  424. s.append("assert(");
  425. s.append(assertion);
  426. s.append(") failed - file: ");
  427. s.append(file);
  428. s.append(", line ");
  429. s.append(line);
  430. ERRLOG("%s",s.str()); // make sure doesn't get lost!
  431. queryLogMsgManager()->flushQueue(10*1000);
  432. #ifdef _DEBUG
  433. // cause a breakpoint in the debugger if we are debugging.
  434. //userBreakpoint();
  435. #endif
  436. #if 0
  437. #ifndef USING_MPATROL
  438. #ifdef _WIN32
  439. // disable memory leak dump since it is meaningless in this case
  440. int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
  441. tmpFlag &= ~_CRTDBG_LEAK_CHECK_DF;
  442. _CrtSetDbgFlag( tmpFlag );
  443. #endif
  444. #endif
  445. #endif
  446. throw MakeStringExceptionDirect(3000, s.toCharArray()); // 3000: internal error
  447. }
  448. void RaiseAssertCore(const char *assertion, const char *file, unsigned line)
  449. {
  450. PrintStackReport();
  451. StringBuffer s;
  452. s.append("assert(");
  453. s.append(assertion);
  454. s.append(") failed - file: ");
  455. s.append(file);
  456. s.append(", line ");
  457. s.append(line);
  458. ERRLOG("%s",s.str()); // make sure doesn't get lost!
  459. queryLogMsgManager()->flushQueue(10*1000);
  460. #ifdef _WIN32
  461. userBreakpoint();
  462. ExitProcess(255);
  463. #else
  464. raise(SIGABRT);
  465. _exit(255);
  466. #endif
  467. }
  468. static int SEHnested = 0;
  469. static IExceptionHandler *SEHHandler = NULL;
  470. static bool SEHtermOnSystemDLLs = false;
  471. static bool SEHtermAlways = false;
  472. #ifdef _WIN32
  473. static void *SEHrestore;
  474. #ifdef EXTENDED_EXCEPTION_TRACE
  475. static LPTSTR GetExceptionString( DWORD dwCode )
  476. {
  477. #define EXCEPTION( x ) case EXCEPTION_##x: return #x;
  478. switch ( dwCode )
  479. {
  480. EXCEPTION( ACCESS_VIOLATION )
  481. EXCEPTION( DATATYPE_MISALIGNMENT )
  482. EXCEPTION( BREAKPOINT )
  483. EXCEPTION( SINGLE_STEP )
  484. EXCEPTION( ARRAY_BOUNDS_EXCEEDED )
  485. EXCEPTION( FLT_DENORMAL_OPERAND )
  486. EXCEPTION( FLT_DIVIDE_BY_ZERO )
  487. EXCEPTION( FLT_INEXACT_RESULT )
  488. EXCEPTION( FLT_INVALID_OPERATION )
  489. EXCEPTION( FLT_OVERFLOW )
  490. EXCEPTION( FLT_STACK_CHECK )
  491. EXCEPTION( FLT_UNDERFLOW )
  492. EXCEPTION( INT_DIVIDE_BY_ZERO )
  493. EXCEPTION( INT_OVERFLOW )
  494. EXCEPTION( PRIV_INSTRUCTION )
  495. EXCEPTION( IN_PAGE_ERROR )
  496. EXCEPTION( ILLEGAL_INSTRUCTION )
  497. EXCEPTION( NONCONTINUABLE_EXCEPTION )
  498. EXCEPTION( STACK_OVERFLOW )
  499. EXCEPTION( INVALID_DISPOSITION )
  500. EXCEPTION( GUARD_PAGE )
  501. EXCEPTION( INVALID_HANDLE )
  502. }
  503. static CHAR szBuffer[512] = { 0 };
  504. FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
  505. GetModuleHandle( "NTDLL.DLL" ),
  506. dwCode, 0, szBuffer, sizeof( szBuffer ), 0 );
  507. return szBuffer;
  508. }
  509. static BOOL GetLogicalAddress( PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset )
  510. {
  511. szModule[0] = 0;
  512. section = 0;
  513. offset = 0;
  514. if ((unsigned)addr<0x10000)
  515. return FALSE;
  516. MEMORY_BASIC_INFORMATION mbi;
  517. if ( !VirtualQuery( addr, &mbi, sizeof(mbi) ) )
  518. return FALSE;
  519. DWORD hMod = (DWORD)mbi.AllocationBase;
  520. if ( !GetModuleFileName( (HMODULE)hMod, szModule, len ) )
  521. return FALSE;
  522. PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
  523. PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew);
  524. PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr );
  525. DWORD rva = (DWORD)addr - hMod;
  526. for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++ )
  527. {
  528. DWORD sectionStart = pSection->VirtualAddress;
  529. DWORD sectionEnd = sectionStart
  530. + std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize);
  531. if ( (rva >= sectionStart) && (rva <= sectionEnd) )
  532. {
  533. section = i+1;
  534. offset = rva - sectionStart;
  535. return TRUE;
  536. }
  537. }
  538. return FALSE;
  539. }
  540. #if defined(_WIN32)
  541. #ifdef __cplusplus
  542. extern "C" {
  543. typedef BOOL (CALLBACK* LPENUMPROCESSMODULES)(HANDLE,HMODULE *,DWORD,LPDWORD);
  544. typedef BOOL (CALLBACK* LPGETMODULEINFORMATION)(HANDLE,HMODULE,LPMODULEINFO,DWORD);
  545. }
  546. #endif
  547. #endif
  548. static void ModuleWalk()
  549. {
  550. HMODULE hmSystem = LoadLibrary("psapi.dll");
  551. if (!hmSystem)
  552. return;
  553. LPENUMPROCESSMODULES enumProcessModules = (LPENUMPROCESSMODULES)GetProcAddress(hmSystem,"EnumProcessModules");
  554. if (!enumProcessModules)
  555. return;
  556. LPGETMODULEINFORMATION getModuleInformation = (LPGETMODULEINFORMATION)GetProcAddress(hmSystem,"GetModuleInformation");
  557. if (!getModuleInformation)
  558. return;
  559. DWORD processID = GetCurrentProcessId();
  560. PrintLog( "Process ID: %u", processID );
  561. // Get a list of all the modules in this process.
  562. HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
  563. PROCESS_VM_READ,
  564. FALSE, processID );
  565. if (NULL == hProcess)
  566. return;
  567. HMODULE hMods[1024];
  568. DWORD cbNeeded;
  569. if (enumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
  570. for (unsigned i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ ) {
  571. char szModName[MAX_PATH];
  572. szModName[0] = 0;
  573. // Get the full path to the module's file.
  574. MODULEINFO modinfo;
  575. memset(&modinfo,0,sizeof(modinfo));
  576. getModuleInformation(hProcess, hMods[i], &modinfo, sizeof(modinfo));
  577. GetModuleFileName( hMods[i], szModName, sizeof(szModName));
  578. PrintLog("%8X %8X %8X %s",(unsigned)modinfo.lpBaseOfDll,(unsigned)modinfo.SizeOfImage,(unsigned)modinfo.EntryPoint,szModName);
  579. }
  580. }
  581. CloseHandle( hProcess );
  582. FreeLibrary(hmSystem);
  583. }
  584. static void StackWalk( size_t pc, size_t bp )
  585. {
  586. PrintLog( "Call stack:" );
  587. PrintLog( "Address Frame Logical addr Module" );
  588. size_t * pFrame;
  589. size_t * pPrevFrame=NULL;
  590. pFrame = (size_t*)bp;
  591. do
  592. {
  593. TCHAR szModule[MAX_PATH] = "";
  594. DWORD section = 0, offset = 0;
  595. if (pc>0x10000)
  596. GetLogicalAddress((PVOID)pc, szModule,sizeof(szModule),section,offset );
  597. else
  598. strcpy(szModule,"NULL");
  599. PrintLog( "%08X %08X %04X:%08X %s",
  600. pc, pFrame, section, offset, szModule );
  601. if ( (size_t)pFrame & 0x80000003 )
  602. break;
  603. if ( (size_t)pFrame <= (size_t)pPrevFrame )
  604. break;
  605. if ( IsBadWritePtr(pFrame, sizeof(PVOID)*2) )
  606. break;
  607. pc = pFrame[1];
  608. if ( IsBadCodePtr((FARPROC) pc) )
  609. break;
  610. pPrevFrame = pFrame;
  611. pFrame = (size_t *)pFrame[0];
  612. } while ( 1 );
  613. }
  614. static void doPrintStackReport( size_t ip, size_t _bp, size_t sp )
  615. {
  616. if (_bp==0) {
  617. #ifdef _AMD64_
  618. PrintLog("inline assembler is not supported in 64bit AMD compiler; StackReport incomplete bp tend to not be used");
  619. #else
  620. __asm {
  621. mov eax,ebp
  622. mov _bp,eax
  623. }
  624. #endif
  625. }
  626. for (unsigned i=0;i<8;i++) {
  627. StringBuffer s;
  628. #ifdef _AMD64_
  629. s.appendf("Stack[%016X]:",sp);
  630. #else
  631. s.appendf("Stack[%08X]:",sp);
  632. #endif
  633. for (unsigned j=0;j<8;j++) {
  634. if ( IsBadReadPtr((const void *)sp, sizeof(unsigned)) )
  635. break;
  636. size_t v = *(size_t *)sp;
  637. sp += sizeof(unsigned);
  638. #ifdef _AMD64_
  639. s.appendf(" %016X",v);
  640. #else
  641. s.appendf(" %08X",v);
  642. #endif
  643. }
  644. PrintLog( "%s",s.str());
  645. }
  646. StackWalk( ip , _bp);
  647. ModuleWalk();
  648. StringBuffer threadlist;
  649. PrintLog( "ThreadList:\n%s",getThreadList(threadlist).str());
  650. }
  651. static void PrintExceptionReport( PEXCEPTION_POINTERS pExceptionInfo)
  652. {
  653. PrintLog("=====================================================");
  654. PrintMemoryStatusLog();
  655. PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
  656. PrintLog( "Exception code: %08X %s",
  657. pExceptionRecord->ExceptionCode,
  658. GetExceptionString(pExceptionRecord->ExceptionCode) );
  659. PrintLog( "Fault address: %08X", pExceptionRecord->ExceptionAddress);
  660. TCHAR szFaultingModule[MAX_PATH];
  661. DWORD section, offset;
  662. GetLogicalAddress( pExceptionRecord->ExceptionAddress,
  663. szFaultingModule,
  664. sizeof( szFaultingModule ),
  665. section, offset );
  666. PrintLog("Fault module: %02X:%08X %s", section, offset, szFaultingModule);
  667. PCONTEXT pCtx = pExceptionInfo->ContextRecord;
  668. PrintLog( "\nRegisters:" );
  669. #ifdef _AMD64_
  670. PrintLog("RAX:%016" I64F "X RBX:%016" I64F "X RCX:%016" I64F "X RDX:%016" I64F "X RSI:%016" I64F "X RDI:%016" I64F "X",
  671. pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, pCtx->Rsi, pCtx->Rdi );
  672. PrintLog( "CS:RIP:%04X:%016" I64F "X", pCtx->SegCs, pCtx->Rip );
  673. PrintLog( "SS:PSP:%04X:%016" I64F "X PBP:%016" I64F "X",
  674. pCtx->SegSs, pCtx->Rsp, pCtx->Rbp );
  675. #else
  676. PrintLog("EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X",
  677. pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, pCtx->Esi, pCtx->Edi );
  678. PrintLog( "CS:EIP:%04X:%08X", pCtx->SegCs, pCtx->Eip );
  679. PrintLog( "SS:ESP:%04X:%08X EBP:%08X",
  680. pCtx->SegSs, pCtx->Esp, pCtx->Ebp );
  681. #endif
  682. PrintLog( "DS:%04X ES:%04X FS:%04X GS:%04X",
  683. pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs );
  684. PrintLog( "Flags:%08X", pCtx->EFlags );
  685. #ifdef _AMD64_
  686. doPrintStackReport(pCtx->Rip, pCtx->Rbp,pCtx->Rsp);
  687. #else
  688. doPrintStackReport(pCtx->Eip, pCtx->Ebp,pCtx->Esp);
  689. #endif
  690. if (SEHtermOnSystemDLLs || SEHtermAlways) {
  691. char *s = szFaultingModule;
  692. while (*s) {
  693. char *sep = strchr(s,'\\');
  694. if (!sep) {
  695. sep = strchr(s,'.');
  696. if (sep)
  697. *sep = 0;
  698. break;
  699. }
  700. s = sep+1;
  701. }
  702. if (SEHtermAlways || (stricmp(s,"ntdll")==0)||(stricmp(s,"kernel32")==0)||(stricmp(s,"msvcrt")==0)||(stricmp(s,"msvcrtd")==0)) {
  703. TerminateProcess(GetCurrentProcess(), 1);
  704. }
  705. }
  706. }
  707. class jlib_thrown_decl CSEHException: public CInterface, public ISEH_Exception
  708. {
  709. public:
  710. IMPLEMENT_IINTERFACE;
  711. CSEHException(unsigned int u, _EXCEPTION_POINTERS* pExp) : errcode((int)u)
  712. {
  713. #ifdef EXTENDED_EXCEPTION_TRACE
  714. PrintExceptionReport(pExp);
  715. #endif
  716. #ifdef ALLREGS
  717. char s[256]; // not too good on stack faults!
  718. sprintf(s,"SEH Exception(%x)\n"
  719. "EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X\n"
  720. "EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X\n"
  721. "CS=%04X DS=%04X SS=%04X ES=%04X FS=%04X GS=%04X",
  722. u,
  723. pExp->ContextRecord->Eax, pExp->ContextRecord->Ebx,
  724. pExp->ContextRecord->Ecx, pExp->ContextRecord->Edx,
  725. pExp->ContextRecord->Esi, pExp->ContextRecord->Edi,
  726. pExp->ContextRecord->Ebp, pExp->ContextRecord->Esp,
  727. pExp->ContextRecord->Eip, pExp->ContextRecord->EFlags,
  728. pExp->ContextRecord->SegCs, pExp->ContextRecord->SegDs,
  729. pExp->ContextRecord->SegSs, pExp->ContextRecord->SegEs,
  730. pExp->ContextRecord->SegFs, pExp->ContextRecord->SegGs);
  731. #else
  732. char s[80];
  733. #ifdef _AMD64_
  734. sprintf(s,"SEH Exception(%08X) at %04X:%016" I64F "X\n",u,pExp->ContextRecord->SegCs,pExp->ContextRecord->Rip);
  735. #else
  736. sprintf(s,"SEH Exception(%08X) at %04X:%08X\n",u,pExp->ContextRecord->SegCs,pExp->ContextRecord->Eip);
  737. #endif
  738. #endif
  739. msg.set(s);
  740. };
  741. int errorCode() const { return errcode; }
  742. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  743. MessageAudience errorAudience() const { return MSGAUD_user; }
  744. static void Translate(unsigned int u, _EXCEPTION_POINTERS* pExp)
  745. {
  746. #ifdef _DEBUG
  747. if (u == 0x80000003) return; // int 3 breakpoints
  748. static CriticalSection crit;
  749. {
  750. CriticalBlock b(crit);
  751. PrintExceptionReport(pExp);
  752. }
  753. #endif
  754. ISEH_Exception *e = new CSEHException(u,pExp);
  755. if (SEHHandler && SEHHandler->fireException(e)) return;
  756. throw(e);
  757. }
  758. protected:
  759. int errcode;
  760. StringAttr msg;
  761. };
  762. #endif
  763. #else
  764. #ifdef LINUX_SIGNAL_EXCEPTION
  765. static IException *sigsegv_exc;
  766. static int excsignal;
  767. class jlib_thrown_decl CSEHException: public CInterface, public ISEH_Exception
  768. {
  769. public:
  770. IMPLEMENT_IINTERFACE;
  771. CSEHException(int signum, const char *s)
  772. {
  773. errcode = signum;
  774. msg.set(s);
  775. };
  776. int errorCode() const { return errcode; }
  777. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  778. MessageAudience errorAudience() const { return MSGAUD_user; }
  779. protected:
  780. int errcode;
  781. StringAttr msg;
  782. };
  783. static void throwSigSegV()
  784. {
  785. int childpid = fork();
  786. if (childpid <= 0) { // the child
  787. // generate a coredump on different process
  788. signal(excsignal, SIG_DFL);
  789. raise(excsignal);
  790. return;
  791. }
  792. PROGLOG("Dumping core using child process %d",childpid);
  793. waitpid(childpid, NULL, 0);
  794. if (SEHHandler && SEHHandler->fireException(sigsegv_exc))
  795. return;
  796. throw sigsegv_exc;
  797. }
  798. void excsighandler(int signum, siginfo_t *info, void *extra)
  799. {
  800. static byte nested=0;
  801. if (nested++)
  802. return;
  803. #ifdef NO_LINUX_SEH
  804. signal(SIGSEGV, SIG_DFL);
  805. signal(SIGBUS, SIG_DFL);
  806. signal(SIGILL, SIG_DFL);
  807. signal(SIGFPE, SIG_DFL);
  808. #endif
  809. StringBuffer s;
  810. #if __WORDSIZE == 64
  811. #define I64X "%016" I64F "X"
  812. ucontext_t *uc = (ucontext_t *)extra;
  813. #ifdef __APPLE__
  814. __int64 ip = uc->uc_mcontext->__ss.__rip;
  815. __int64 sp = uc->uc_mcontext->__ss.__rsp;
  816. #else
  817. __int64 ip = uc->uc_mcontext.gregs[REG_RIP];
  818. __int64 sp = uc->uc_mcontext.gregs[REG_RSP];
  819. #endif
  820. excsignal = signum;
  821. s.appendf("SIG: %s(%d), accessing "I64X", IP="I64X, strsignal(signum),signum, (__int64)info->si_addr, ip);
  822. PROGLOG("================================================");
  823. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  824. PROGLOG("Fault IP: "I64X"", ip);
  825. PROGLOG("Accessing: "I64X"", (unsigned __int64) info->si_addr);
  826. PROGLOG("Registers:" );
  827. PROGLOG("EAX:"I64X" EBX:"I64X" ECX:"I64X" EDX:"I64X" ESI:"I64X" EDI:"I64X"",
  828. #ifdef __APPLE__
  829. (unsigned __int64) uc->uc_mcontext->__ss.__rax, (unsigned __int64)uc->uc_mcontext->__ss.__rbx,
  830. (unsigned __int64) uc->uc_mcontext->__ss.__rcx, (unsigned __int64)uc->uc_mcontext->__ss.__rdx,
  831. (unsigned __int64) uc->uc_mcontext->__ss.__rsi, (unsigned __int64)uc->uc_mcontext->__ss.__rdi);
  832. PROGLOG( "CS:EIP:%04X:"I64X"", ((unsigned) uc->uc_mcontext->__ss.__cs)&0xffff, ip );
  833. PROGLOG( " ESP:"I64X" EBP:"I64X"", sp, (unsigned __int64) uc->uc_mcontext->__ss.__rbp );
  834. #else
  835. (unsigned __int64) uc->uc_mcontext.gregs[REG_RAX], (unsigned __int64)uc->uc_mcontext.gregs[REG_RBX],
  836. (unsigned __int64) uc->uc_mcontext.gregs[REG_RCX], (unsigned __int64) uc->uc_mcontext.gregs[REG_RDX],
  837. (unsigned __int64) uc->uc_mcontext.gregs[REG_RSI], (unsigned __int64) uc->uc_mcontext.gregs[REG_RDI] );
  838. PROGLOG( "CS:EIP:%04X:"I64X"", ((unsigned) uc->uc_mcontext.gregs[REG_CSGSFS])&0xffff, ip );
  839. PROGLOG( " ESP:"I64X" EBP:"I64X"", sp, (unsigned __int64) uc->uc_mcontext.gregs[REG_RBP] );
  840. #endif
  841. for (unsigned i=0;i<8;i++) {
  842. StringBuffer s;
  843. s.appendf("Stack["I64X"]:",sp);
  844. for (unsigned j=0;j<8;j++) {
  845. __int64 v = *(size_t *)sp;
  846. sp += sizeof(unsigned);
  847. s.appendf(" "I64X"",v);
  848. }
  849. PROGLOG( "%s",s.str());
  850. }
  851. #elif defined (__linux__)
  852. ucontext_t *uc = (ucontext_t *)extra;
  853. unsigned ip = uc->uc_mcontext.gregs[REG_EIP];
  854. unsigned sp = uc->uc_mcontext.gregs[REG_ESP];
  855. excsignal = signum;
  856. s.appendf("SIG: %s(%d), accessing %p, IP=%x", strsignal(signum),signum, info->si_addr, ip);
  857. PROGLOG("================================================");
  858. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  859. PROGLOG("Fault IP: %08X", ip);
  860. PROGLOG("Accessing: %08X", info->si_addr);
  861. PROGLOG("Registers:" );
  862. PROGLOG("EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X",
  863. uc->uc_mcontext.gregs[REG_EAX], uc->uc_mcontext.gregs[REG_EBX],
  864. uc->uc_mcontext.gregs[REG_ECX], uc->uc_mcontext.gregs[REG_EDX],
  865. uc->uc_mcontext.gregs[REG_ESI], uc->uc_mcontext.gregs[REG_EDI] );
  866. PROGLOG( "CS:EIP:%04X:%08X", uc->uc_mcontext.gregs[REG_CS], ip );
  867. PROGLOG( "SS:ESP:%04X:%08X EBP:%08X",
  868. uc->uc_mcontext.gregs[REG_SS], sp, uc->uc_mcontext.gregs[REG_EBP] );
  869. for (unsigned i=0;i<8;i++) {
  870. StringBuffer s;
  871. s.appendf("Stack[%08X]:",sp);
  872. for (unsigned j=0;j<8;j++) {
  873. size_t v = *(size_t *)sp;
  874. sp += sizeof(unsigned);
  875. s.appendf(" %08X",v);
  876. }
  877. PROGLOG( "%s",s.str());
  878. }
  879. PROGLOG("Frame:");
  880. unsigned* bp = (unsigned*) (uc->uc_mcontext.gregs[REG_EBP]);
  881. for (unsigned n=0; n<64; n++) {
  882. unsigned * nextbp = (unsigned *) *bp++;
  883. unsigned fip = *bp;
  884. if ((fip < 0x08000000) || (fip > 0x7fffffff) || (nextbp < bp))
  885. break;
  886. PROGLOG("%2d %08X %08X",n+1,fip,(unsigned) bp);
  887. bp = nextbp;
  888. }
  889. #endif
  890. #ifdef _EXECINFO_H
  891. PrintStackReport();
  892. #endif
  893. StringBuffer threadlist;
  894. PROGLOG( "ThreadList:\n%s",getThreadList(threadlist).str());
  895. queryLogMsgManager()->flushQueue(10*1000);
  896. #ifndef NO_LINUX_SEH
  897. void (* _P)() = throwSigSegV;
  898. uc->uc_mcontext.gregs[REG_ESP]-=4;
  899. uc->uc_mcontext.gregs[REG_EIP] = (unsigned)_P;
  900. unsigned *spp = (unsigned *)sp;
  901. *spp = ip;
  902. sigsegv_exc = new CSEHException(signum,s.str());
  903. #else
  904. if (SEHHandler && SEHHandler->fireException(new CSEHException(signum,s.str())))
  905. return;
  906. #endif
  907. nested--;
  908. }
  909. #endif
  910. #endif
  911. void jlib_decl setTerminateOnSEHInSystemDLLs(bool set)
  912. {
  913. SEHtermOnSystemDLLs = set;
  914. }
  915. void jlib_decl setTerminateOnSEH(bool set)
  916. {
  917. SEHtermAlways = set;
  918. }
  919. void *EnableSEHtranslation()
  920. {
  921. #ifdef NOSEH
  922. return NULL;
  923. #else
  924. #ifdef _WIN32
  925. return _set_se_translator( CSEHException::Translate );
  926. #else
  927. UNIMPLEMENTED;
  928. #endif
  929. #endif
  930. }
  931. void jlib_decl *setSEHtoExceptionHandler(IExceptionHandler *handler)
  932. {
  933. #ifdef NOSEH
  934. return NULL;
  935. #endif
  936. void *ret = SEHHandler;
  937. SEHHandler = handler;
  938. return ret;
  939. }
  940. void jlib_decl EnableSEHtoExceptionMapping()
  941. {
  942. #ifdef NOSEH
  943. return;
  944. #endif
  945. if (SEHnested++)
  946. return; // already done
  947. #ifdef _WIN32
  948. enableThreadSEH();
  949. SEHrestore = EnableSEHtranslation();
  950. #else
  951. struct sigaction act;
  952. sigset_t blockset;
  953. sigemptyset(&blockset);
  954. act.sa_mask = blockset;
  955. act.sa_flags = SA_SIGINFO;
  956. act.sa_sigaction = &excsighandler;
  957. sigaction(SIGSEGV, &act, NULL);
  958. sigaction(SIGILL, &act, NULL);
  959. sigaction(SIGBUS, &act, NULL);
  960. sigaction(SIGFPE, &act, NULL);
  961. #endif
  962. }
  963. void jlib_decl DisableSEHtoExceptionMapping()
  964. {
  965. #ifdef NOSEH
  966. return;
  967. #endif
  968. if (--SEHnested)
  969. return;
  970. #ifdef _WIN32
  971. if (SEHrestore) {
  972. void *restore = SEHrestore;
  973. SEHrestore = NULL;
  974. _set_se_translator( (_se_translator_function)restore );
  975. }
  976. #else
  977. signal(SIGSEGV, SIG_DFL);
  978. signal(SIGBUS, SIG_DFL);
  979. signal(SIGILL, SIG_DFL);
  980. signal(SIGFPE, SIG_DFL);
  981. #endif
  982. }
  983. StringBuffer & formatSystemError(StringBuffer & out, unsigned errcode)
  984. {
  985. #ifdef _WIN32
  986. const char * lpMessageBuffer=NULL;
  987. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  988. NULL,
  989. errcode,
  990. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default
  991. (LPTSTR) &lpMessageBuffer,
  992. 0,
  993. NULL );
  994. if (lpMessageBuffer) {
  995. out.append(lpMessageBuffer);
  996. LocalFree( (void *)lpMessageBuffer );
  997. }
  998. else {
  999. out.append(errcode);
  1000. }
  1001. #else
  1002. int saverr = errno;
  1003. errno = 0;
  1004. const char *errstr = strerror(errcode);
  1005. if (errno==0) {
  1006. out.append(errstr);
  1007. }
  1008. else {
  1009. out.append(errcode);
  1010. }
  1011. errno = saverr;
  1012. #endif
  1013. return out;
  1014. }
  1015. IException * deserializeException(MemoryBuffer & in)
  1016. {
  1017. byte nulle;
  1018. in.read(nulle);
  1019. if (nulle) return NULL;
  1020. int code;
  1021. StringAttr text;
  1022. in.read(code);
  1023. in.read(text);
  1024. return MakeStringException(code, "%s", text.get());
  1025. }
  1026. void jlib_decl serializeException(IException * e, MemoryBuffer & out)
  1027. {
  1028. if (!e)
  1029. out.append((byte)1);
  1030. else
  1031. {
  1032. out.append((byte)0);
  1033. StringBuffer text;
  1034. out.append(e->errorCode());
  1035. out.append(e->errorMessage(text).str());
  1036. }
  1037. }
  1038. void PrintStackReport()
  1039. {
  1040. #ifdef _WIN32
  1041. unsigned onstack=1234;
  1042. doPrintStackReport(0, 0,(unsigned)&onstack);
  1043. #elif defined(__linux__)
  1044. DBGLOG("Backtrace:");
  1045. void *btarray[100];
  1046. unsigned btn = backtrace (btarray, 100);
  1047. char **strings = backtrace_symbols (btarray, btn);
  1048. for (unsigned i=0; i<btn; i++)
  1049. DBGLOG(" %s", strings[i]);
  1050. free (strings);
  1051. #endif
  1052. queryLogMsgManager()->flushQueue(10*1000);
  1053. }
  1054. #ifdef SIGNAL_TO_EXCEPTION
  1055. /*static*/jmp_buf SignalToException::s_jmpbuf;
  1056. /*static*/bool SignalToException::s_bUnixTrapHandlerSet = false;
  1057. SignalToException::SignalToException()
  1058. {
  1059. if (!s_bUnixTrapHandlerSet)
  1060. setUnixTrapHandler();
  1061. memcpy(&m_old_jmpbuf,&s_jmpbuf,sizeof(jmp_buf));
  1062. }
  1063. SignalToException::~SignalToException()
  1064. {
  1065. memcpy(&s_jmpbuf,&m_old_jmpbuf,sizeof(jmp_buf));
  1066. }
  1067. /*static*/
  1068. void SignalToException::UnixTrapHandler(int sig)
  1069. {
  1070. longjmp(SignalToException::s_jmpbuf, sig);
  1071. }
  1072. /*static*/
  1073. void SignalToException::setUnixTrapHandler()
  1074. {
  1075. struct sigaction action;
  1076. sigemptyset(&action.sa_mask);
  1077. action.sa_flags = 0;
  1078. action.sa_handler = UnixTrapHandler;
  1079. int signals[] = {SIGSEGV, SIGILL, SIGFPE, SIGPIPE, SIGSYS};
  1080. for (int i = 0; i < sizeof(signals)/sizeof(signals[0]); i++)
  1081. if ( sigaction(signals[i], &action, NULL) == -1)
  1082. perror("sigaction failed while setting UnixTrapHandler");
  1083. s_bUnixTrapHandlerSet = true;
  1084. }
  1085. /*static*/
  1086. void SignalToException::processSetJmpResult(int res)
  1087. {
  1088. if (res != 0)
  1089. {
  1090. StringBuffer buf("throwing SIG");
  1091. switch (res)
  1092. {
  1093. case SIGSEGV: buf.append("SEGV");
  1094. break;
  1095. case SIGILL : buf.append("ILL" );
  1096. break;
  1097. case SIGFPE : buf.append("FPE" );
  1098. break;
  1099. case SIGPIPE: buf.append("PIPE");
  1100. break;
  1101. case SIGSYS : buf.append("SYS" );
  1102. break;
  1103. default: buf.append("NAL ").append(res);
  1104. break;
  1105. }
  1106. buf.append(" as exception");
  1107. throw MakeStringException(res, "%s", buf.toCharArray());
  1108. }
  1109. }
  1110. #ifdef TEST_SIGNAL_TO_EXCEPTION
  1111. int main(int argc, char**argv)
  1112. {
  1113. TRY
  1114. {
  1115. TRY
  1116. {
  1117. //generate SIGSEGV
  1118. int* p=0;
  1119. *p = 0;
  1120. cout << "Next stmt in inner block!" << endl;
  1121. }
  1122. CATCH(...)
  1123. {
  1124. cout << "inner catch (...)" << endl;
  1125. }
  1126. ENDCATCH;
  1127. //generate SIGFPE
  1128. int p=0;
  1129. int q=2/p;
  1130. cout << "Next stmt in outer block!" << endl;
  1131. }
  1132. CATCH (char*)
  1133. {
  1134. }
  1135. AND_CATCH(...)
  1136. {
  1137. cout << "outer catch (...)" << endl;
  1138. }
  1139. END_CATCH
  1140. return 0;
  1141. }
  1142. #endif //TEST_SIGNAL_TO_EXCEPTION
  1143. #endif //SIGNAL_TO_EXCEPTION
  1144. #ifdef _TEST
  1145. void raise1()
  1146. {
  1147. throw MakeStringException(-1,"test 1");
  1148. }
  1149. void raise2()
  1150. {
  1151. throw MakeOsException(3);
  1152. }
  1153. class DefaultExceptionHandler
  1154. {
  1155. unexpected_handler old;
  1156. public:
  1157. static void handler()
  1158. {
  1159. try {
  1160. throw;
  1161. }
  1162. catch (IException *e) {
  1163. StringBuffer s;
  1164. e->errorMessage(s);
  1165. printf("Unhandled Exception (%d): %s\n",e->errorCode(),(const char *)s.toCharArray());
  1166. e->Release();
  1167. }
  1168. }
  1169. DefaultExceptionHandler() { old = set_terminate(handler); }
  1170. ~DefaultExceptionHandler() { set_terminate(old); }
  1171. } _DefaultExceptionHandler;
  1172. int main()
  1173. {
  1174. try {
  1175. raise1();
  1176. }
  1177. catch (IException *e) {
  1178. StringBuffer s;
  1179. e->errorMessage(s);
  1180. printf("exception %d '%s'\n",e->errorCode(),(const char *)s.toCharArray());
  1181. e->Release();
  1182. }
  1183. try {
  1184. raise2();
  1185. }
  1186. catch (IException *e) {
  1187. StringBuffer s;
  1188. e->errorMessage(s);
  1189. printf("exception %d '%s'\n",e->errorCode(),(const char *)s.toCharArray());
  1190. e->Release();
  1191. }
  1192. raise1();
  1193. return 0;
  1194. }
  1195. #endif