jexcept.cpp 38 KB

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