jexcept.cpp 37 KB

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