jexcept.cpp 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744
  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. const char * errorSeverityString[] = {"Information", "Warning", "Error", "Alert", "Ignore", "Fatal", "Unknown"};
  47. const char * querySeverityString(ErrorSeverity errorSeverity)
  48. {
  49. if (errorSeverity<_elements_in(errorSeverityString))
  50. return errorSeverityString[errorSeverity];
  51. else
  52. return errorSeverityString[SeverityUnknown];
  53. }
  54. class jlib_thrown_decl StringException: public IException, public CInterface
  55. {
  56. public:
  57. IMPLEMENT_IINTERFACE;
  58. StringException(int code, const char *str, MessageAudience aud = MSGAUD_user) : errcode(code), msg(str), audience(aud) {};
  59. int errorCode() const { return errcode; }
  60. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  61. MessageAudience errorAudience() const { return audience; }
  62. protected:
  63. int errcode;
  64. StringAttr msg;
  65. MessageAudience audience;
  66. };
  67. IException *makeStringExceptionVA(int code, const char *format, va_list args)
  68. {
  69. StringBuffer eStr;
  70. eStr.limited_valist_appendf(1024, format, args);
  71. return new StringException(code, eStr.str());
  72. }
  73. IException *makeStringExceptionV(int code,const char *format, ...)
  74. {
  75. va_list args;
  76. va_start(args, format);
  77. IException *ret = makeStringExceptionVA(code, format, args);
  78. va_end(args);
  79. return ret;
  80. }
  81. IException jlib_decl *makeStringException(int code,const char *why)
  82. {
  83. return new StringException(code,why);
  84. }
  85. IException *makeStringExceptionVA(MessageAudience aud, int code, const char *format, va_list args)
  86. {
  87. StringBuffer eStr;
  88. eStr.limited_valist_appendf(1024, format, args);
  89. return new StringException(code, eStr.str(), aud);
  90. }
  91. IException *makeStringExceptionV(MessageAudience aud, int code, const char *format, ...)
  92. {
  93. va_list args;
  94. va_start(args, format);
  95. IException *ret = makeStringExceptionVA(aud, code, format, args);
  96. va_end(args);
  97. return ret;
  98. }
  99. IException jlib_decl *makeStringException(MessageAudience aud,int code,const char *why)
  100. {
  101. return new StringException(code,why,aud);
  102. }
  103. class jlib_thrown_decl WrappedException: public StringException
  104. {
  105. typedef StringException PARENT;
  106. public:
  107. WrappedException(IException *_exception, int code, const char *str, MessageAudience aud = MSGAUD_user) : StringException(code, str, aud), exception(_exception) { }
  108. virtual StringBuffer & errorMessage(StringBuffer &str) const override
  109. {
  110. PARENT::errorMessage(str);
  111. if (exception)
  112. {
  113. str.appendf("[ %u, ", exception->errorCode());
  114. exception->errorMessage(str).append(" ]");
  115. }
  116. return str;
  117. }
  118. protected:
  119. Linked<IException> exception;
  120. };
  121. IException *makeWrappedExceptionVA(IException *e, int code, const char *format, va_list args)
  122. {
  123. StringBuffer eStr;
  124. eStr.limited_valist_appendf(1024, format, args);
  125. return new WrappedException(e, code, eStr.str());
  126. }
  127. IException *makeWrappedExceptionV(IException *e, int code, const char *format, ...)
  128. {
  129. va_list args;
  130. va_start(args, format);
  131. IException *ret = makeWrappedExceptionVA(e, code, format, args);
  132. va_end(args);
  133. return ret;
  134. }
  135. void jlib_decl throwStringExceptionV(int code,const char *format, ...)
  136. {
  137. va_list args;
  138. va_start(args, format);
  139. IException *ret = makeStringExceptionVA(code, format, args);
  140. va_end(args);
  141. throw ret;
  142. }
  143. class jlib_thrown_decl OsException: public IOSException, public CInterface
  144. {
  145. public:
  146. IMPLEMENT_IINTERFACE;
  147. OsException(int code) : errcode(code) {};
  148. OsException(int code, const char *_msg) : msg(_msg), errcode(code) {};
  149. ~OsException() {}
  150. int errorCode() const { return errcode; }
  151. StringBuffer & errorMessage(StringBuffer &str) const
  152. {
  153. if (msg)
  154. str.append(msg).append(", ");
  155. formatSystemError(str, errcode);
  156. return str;
  157. }
  158. MessageAudience errorAudience() const { return MSGAUD_user; }
  159. protected:
  160. StringAttr msg;
  161. int errcode;
  162. };
  163. IOSException *makeOsException(int code)
  164. {
  165. return new OsException(code);
  166. }
  167. IOSException *makeOsException(int code, const char *msg)
  168. {
  169. return new OsException(code, msg);
  170. }
  171. IOSException *makeOsExceptionV(int code, const char *msg, ...)
  172. {
  173. StringBuffer eStr;
  174. va_list args;
  175. va_start(args, msg);
  176. eStr.limited_valist_appendf(1024, msg, args);
  177. va_end(args);
  178. return new OsException(code, eStr.str());
  179. }
  180. class jlib_thrown_decl ErrnoException: public IErrnoException, public CInterface
  181. {
  182. public:
  183. IMPLEMENT_IINTERFACE;
  184. ErrnoException(int errn) : audience(MSGAUD_user) { errcode = errn==-1?errno:errn; }
  185. ErrnoException(int errn, const char *_msg, MessageAudience aud = MSGAUD_user) : msg(_msg), audience(aud) { errcode = errn==-1?errno:errn; }
  186. ~ErrnoException() { }
  187. int errorCode() const { return errcode; }
  188. StringBuffer & errorMessage(StringBuffer &str) const
  189. {
  190. if (msg)
  191. str.append(msg).append(", ");
  192. if (errcode==DISK_FULL_EXCEPTION_CODE)
  193. str.append("Disk full");
  194. else
  195. str.append(strerror(errcode));
  196. return str;
  197. }
  198. MessageAudience errorAudience() const { return audience; }
  199. protected:
  200. StringAttr msg;
  201. int errcode;
  202. MessageAudience audience;
  203. };
  204. IErrnoException *makeErrnoException(int errn, const char *msg)
  205. {
  206. return new ErrnoException(errn, msg);
  207. }
  208. IErrnoException *makeErrnoException(const char *msg)
  209. {
  210. return new ErrnoException(-1, msg);
  211. }
  212. IErrnoException *makeErrnoExceptionV(int errn, const char *msg, ...)
  213. {
  214. StringBuffer eStr;
  215. va_list args;
  216. va_start(args, msg);
  217. eStr.limited_valist_appendf(1024, msg, args);
  218. va_end(args);
  219. return new ErrnoException(errn, eStr.str());
  220. }
  221. IErrnoException *makeErrnoExceptionV(const char *msg, ...)
  222. {
  223. StringBuffer eStr;
  224. va_list args;
  225. va_start(args, msg);
  226. eStr.limited_valist_appendf(1024, msg, args);
  227. va_end(args);
  228. return new ErrnoException(-1, eStr.str());
  229. }
  230. IErrnoException *makeErrnoException(MessageAudience aud, int errn, const char *msg)
  231. {
  232. return new ErrnoException(errn, msg, aud);
  233. }
  234. IErrnoException *makeErrnoExceptionV(MessageAudience aud, int errn, const char *msg, ...)
  235. {
  236. StringBuffer eStr;
  237. va_list args;
  238. va_start(args, msg);
  239. eStr.limited_valist_appendf(1024, msg, args);
  240. va_end(args);
  241. return new ErrnoException(errn, eStr.str(), aud);
  242. }
  243. IErrnoException *makeErrnoExceptionV(MessageAudience aud, const char *msg, ...)
  244. {
  245. StringBuffer eStr;
  246. va_list args;
  247. va_start(args, msg);
  248. eStr.limited_valist_appendf(1024, msg, args);
  249. va_end(args);
  250. return new ErrnoException(-1, eStr.str(), aud);
  251. }
  252. const char* serializeMessageAudience(MessageAudience ma)
  253. {
  254. const char* ret;
  255. switch(ma)
  256. {
  257. case MSGAUD_operator: ret = "operator"; break;
  258. case MSGAUD_user: ret = "user"; break;
  259. case MSGAUD_programmer: ret = "programmer"; break;
  260. case MSGAUD_legacy: ret = "legacy"; break;
  261. case MSGAUD_all: ret = "all"; break;
  262. default: ret = "unknown"; break;
  263. }
  264. return ret;
  265. }
  266. MessageAudience deserializeMessageAudience(const char* text)
  267. {
  268. MessageAudience ma = MSGAUD_programmer;
  269. if (text && *text)
  270. {
  271. if (!strcmp(text, "operator"))
  272. ma = MSGAUD_operator;
  273. else if (!strcmp(text, "user"))
  274. ma = MSGAUD_user;
  275. else if (!strcmp(text, "programmer"))
  276. ma = MSGAUD_programmer;
  277. else if (!strcmp(text, "legacy"))
  278. ma = MSGAUD_legacy;
  279. else if (!strcmp(text, "all"))
  280. ma = MSGAUD_all;
  281. }
  282. return ma;
  283. }
  284. class jlib_thrown_decl CMultiException : implements IMultiException, public CInterface
  285. {
  286. public:
  287. IMPLEMENT_IINTERFACE
  288. CMultiException(const char* source=NULL)
  289. {
  290. if (source)
  291. source_.append(source);
  292. }
  293. //convenience methods for handling this as an array
  294. virtual aindex_t ordinality() const
  295. {
  296. synchronized block(m_mutex);
  297. return array_.ordinality();
  298. }
  299. virtual IException& item(aindex_t pos) const
  300. {
  301. synchronized block(m_mutex);
  302. return array_.item(pos);
  303. }
  304. virtual const char* source() const
  305. {
  306. synchronized block(m_mutex);
  307. return source_.str();
  308. }
  309. //for complete control...caller is responsible for thread safety!
  310. virtual IArrayOf<IException>& getArray() { return array_; }
  311. //add another exception
  312. virtual void append(IException& e)
  313. {
  314. synchronized block(m_mutex);
  315. array_.append(e);
  316. }
  317. virtual void append(IMultiException& me)
  318. {
  319. synchronized block(m_mutex);
  320. IArrayOf<IException>& exceptions = me.getArray();
  321. const char* source = me.source();
  322. ForEachItemIn(i, exceptions)
  323. {
  324. IException& e = exceptions.item(i);
  325. if (source && *source)
  326. {
  327. StringBuffer msg;
  328. msg.appendf("[%s] ",source);
  329. e.errorMessage(msg);
  330. array_.append(*makeStringExceptionV(e.errorAudience(), e.errorCode(), "%s", msg.str()));
  331. }
  332. else
  333. array_.append(*LINK(&e));
  334. }
  335. }
  336. StringBuffer& serialize(StringBuffer& buffer, unsigned indent = 0, bool simplified=false, bool root=true) const
  337. {
  338. synchronized block(m_mutex);
  339. if (root)
  340. buffer.append("<Exceptions>");
  341. if (!simplified)
  342. {
  343. if (indent) buffer.append("\n\t");
  344. buffer.appendf("<Source>%s</Source>", source_.str());
  345. }
  346. ForEachItemIn(i, array_)
  347. {
  348. IException& exception = array_.item(i);
  349. if (indent) buffer.append("\n\t");
  350. buffer.append("<Exception>");
  351. //tag order is important for some soap clients (i.e. Java Axis)
  352. if (indent) buffer.append("\n\t\t");
  353. buffer.appendf("<Code>%d</Code>", exception.errorCode());
  354. if (indent) buffer.append("\n\t\t");
  355. buffer.appendf("<Audience>%s</Audience>", serializeMessageAudience( exception.errorAudience() ));
  356. if (simplified)
  357. {
  358. if (indent) buffer.append("\n\t\t");
  359. StringBuffer msg;
  360. buffer.appendf("<Source>%s</Source>", source_.str());
  361. }
  362. if (indent) buffer.append("\n\t\t");
  363. StringBuffer msg;
  364. StringBuffer encoded;
  365. encodeXML(exception.errorMessage(msg).str(), encoded);
  366. buffer.appendf("<Message>%s</Message>", encoded.str());
  367. if (indent) buffer.append("\n\t");
  368. buffer.append("</Exception>");
  369. }
  370. if (root)
  371. buffer.append("</Exceptions>");
  372. return buffer;
  373. }
  374. StringBuffer& serializeJSON(StringBuffer& buffer, unsigned indent = 0, bool simplified=false, bool root=true, bool enclose=false) const
  375. {
  376. synchronized block(m_mutex);
  377. if (enclose)
  378. {
  379. buffer.append("{");
  380. if (indent) buffer.append("\n");
  381. }
  382. if (root)
  383. buffer.append("\"Exceptions\": {");
  384. if (!simplified)
  385. {
  386. if (indent) buffer.append("\n\t");
  387. buffer.appendf("\"Source\": \"%s\"", source_.str());
  388. }
  389. ForEachItemIn(i, array_)
  390. {
  391. if (i == 0 && !simplified)
  392. buffer.appendf(", ");
  393. else if (i > 0)
  394. buffer.append(", ");
  395. IException& exception = array_.item(i);
  396. if (indent) buffer.append("\n\t");
  397. if (i == 0)
  398. buffer.append("\"Exception\": [");
  399. if (indent) buffer.append("\n\t");
  400. buffer.append("{");
  401. if (indent) buffer.append("\n\t\t");
  402. buffer.appendf("\"Code\": %d,", exception.errorCode());
  403. if (indent) buffer.append("\n\t\t");
  404. buffer.appendf("\"Audience\": \"%s\",", serializeMessageAudience( exception.errorAudience() ));
  405. if (!simplified)
  406. {
  407. if (indent) buffer.append("\n\t\t");
  408. buffer.appendf("\"Source\": \"%s\",", source_.str());
  409. }
  410. if (indent) buffer.append("\n\t\t");
  411. StringBuffer msg;
  412. StringBuffer encoded;
  413. encodeJSON(encoded, exception.errorMessage(msg).str());
  414. buffer.appendf("\"Message\": \"%s\"", encoded.str());
  415. if (indent) buffer.append("\n\t");
  416. buffer.append("}");
  417. }
  418. if (indent) buffer.append("\n\t");
  419. buffer.append("]");
  420. if (root)
  421. {
  422. if (indent) buffer.append("\n");
  423. buffer.append("}");
  424. }
  425. if (enclose)
  426. {
  427. if (indent) buffer.append("\n");
  428. buffer.append("}");
  429. }
  430. return buffer;
  431. }
  432. virtual void deserialize(const char* xml)
  433. {
  434. synchronized block(m_mutex);
  435. StringBuffer wrapper;
  436. if (strncmp(xml, "<Exceptions>", 12))
  437. xml = wrapper.appendf("<Exceptions>%s</Exceptions>", xml).str();
  438. Owned<IPropertyTree> pTree = createPTreeFromXMLString(xml);
  439. if (!pTree)
  440. throw makeStringException(-1, "Failed to deserialize IMultiException!");
  441. Owned<IPropertyTreeIterator> i = pTree->getElements("Exception");
  442. if (pTree->hasProp("Source"))
  443. source_.clear().append( pTree->queryProp("Source"));
  444. else
  445. {
  446. if (i->first())
  447. {
  448. IPropertyTree* pNode = &i->query();
  449. source_.clear().append( pNode->queryProp("Source"));
  450. }
  451. }
  452. array_.kill();
  453. ForEach(*i)
  454. {
  455. IPropertyTree* pNode = &i->query();
  456. IException* pException =
  457. makeStringException(
  458. deserializeMessageAudience(pNode->queryProp("Audience")),
  459. pNode->getPropInt("Code", -1),
  460. pNode->queryProp("Message"));
  461. array_.append(*pException);
  462. }
  463. }
  464. //the following methods override those in IIException
  465. //
  466. virtual int errorCode() const
  467. {
  468. synchronized block(m_mutex);
  469. return ordinality() == 1 ? item(0).errorCode() : -1;
  470. }
  471. virtual StringBuffer& errorMessage(StringBuffer &msg) const
  472. {
  473. synchronized block(m_mutex);
  474. ForEachItemIn(i, array_)
  475. {
  476. IException& e = item(i);
  477. StringBuffer buf;
  478. msg.appendf("[%3d: %s] ", e.errorCode(), e.errorMessage(buf).str());
  479. }
  480. return msg;
  481. }
  482. virtual MessageAudience errorAudience() const
  483. {
  484. synchronized block(m_mutex);
  485. return ordinality() == 1 ? item(0).errorAudience() : MSGAUD_programmer;
  486. }
  487. private:
  488. CMultiException( const CMultiException& );
  489. IArrayOf<IException> array_;
  490. StringBuffer source_;
  491. mutable Mutex m_mutex;
  492. };
  493. IMultiException *makeMultiException(const char* source/*=NULL*/)
  494. {
  495. return new CMultiException(source);
  496. }
  497. void pexception(const char *msg,IException *e)
  498. { // like perror except for exceptions
  499. StringBuffer s;
  500. fprintf(stderr,"%s : %s\n",msg,e?e->errorMessage(s).str():"NULL Exception!");
  501. }
  502. void userBreakpoint()
  503. {
  504. #ifdef _WIN32
  505. try
  506. {
  507. DebugBreak();
  508. }
  509. catch (...)
  510. {
  511. //if not debugging don't give an unhandled exception.
  512. }
  513. #endif
  514. }
  515. const char *sanitizeSourceFile(const char *file)
  516. {
  517. if (file)
  518. {
  519. const char *tail = strrchr(file, '/');
  520. if (tail)
  521. return tail+1;
  522. #ifdef _WIN32
  523. tail = strrchr(file, '\\');
  524. if (tail)
  525. return tail+1;
  526. #endif
  527. }
  528. return file;
  529. }
  530. void throwUnexpectedException(const char * file, unsigned line)
  531. {
  532. printStackReport();
  533. throw makeStringExceptionV(9999, "Internal Error at %s(%d)", sanitizeSourceFile(file), line);
  534. }
  535. void throwUnexpectedException(const char * where, const char * file, unsigned line)
  536. {
  537. printStackReport();
  538. throw makeStringExceptionV(9999, "Internal Error '%s' at %s(%d)", where, sanitizeSourceFile(file), line);
  539. }
  540. void raiseAssertException(const char *assertion, const char *file, unsigned line)
  541. {
  542. StringBuffer s;
  543. s.append("assert(");
  544. s.append(assertion);
  545. s.append(") failed - file: ");
  546. s.append(sanitizeSourceFile(file));
  547. s.append(", line ");
  548. s.append(line);
  549. if (queryLogMsgManager())
  550. {
  551. printStackReport();
  552. IERRLOG("%s",s.str()); // make sure doesn't get lost!
  553. queryLogMsgManager()->flushQueue(10*1000);
  554. #ifdef _DEBUG
  555. // cause a breakpoint in the debugger if we are debugging.
  556. //userBreakpoint();
  557. #endif
  558. }
  559. #if 0
  560. #ifndef USING_MPATROL
  561. #ifdef _WIN32
  562. // disable memory leak dump since it is meaningless in this case
  563. int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
  564. tmpFlag &= ~_CRTDBG_LEAK_CHECK_DF;
  565. _CrtSetDbgFlag( tmpFlag );
  566. #endif
  567. #endif
  568. #endif
  569. throw makeStringException(3000, s.str()); // 3000: internal error
  570. }
  571. void raiseAssertCore(const char *assertion, const char *file, unsigned line)
  572. {
  573. printStackReport();
  574. StringBuffer s;
  575. s.append("assert(");
  576. s.append(assertion);
  577. s.append(") failed - file: ");
  578. s.append(sanitizeSourceFile(file));
  579. s.append(", line ");
  580. s.append(line);
  581. IERRLOG("%s",s.str()); // make sure doesn't get lost!
  582. queryLogMsgManager()->flushQueue(10*1000);
  583. #ifdef _WIN32
  584. userBreakpoint();
  585. ExitProcess(255);
  586. #else
  587. raise(SIGABRT);
  588. _exit(255);
  589. #endif
  590. }
  591. static int SEHnested = 0;
  592. static IExceptionHandler *SEHHandler = NULL;
  593. static bool SEHtermOnSystemDLLs = false;
  594. static bool SEHtermAlways = false;
  595. #ifdef _WIN32
  596. static void *SEHrestore;
  597. #ifdef EXTENDED_EXCEPTION_TRACE
  598. static LPTSTR GetExceptionString( DWORD dwCode )
  599. {
  600. #define EXCEPTION( x ) case EXCEPTION_##x: return #x;
  601. switch ( dwCode )
  602. {
  603. EXCEPTION( ACCESS_VIOLATION )
  604. EXCEPTION( DATATYPE_MISALIGNMENT )
  605. EXCEPTION( BREAKPOINT )
  606. EXCEPTION( SINGLE_STEP )
  607. EXCEPTION( ARRAY_BOUNDS_EXCEEDED )
  608. EXCEPTION( FLT_DENORMAL_OPERAND )
  609. EXCEPTION( FLT_DIVIDE_BY_ZERO )
  610. EXCEPTION( FLT_INEXACT_RESULT )
  611. EXCEPTION( FLT_INVALID_OPERATION )
  612. EXCEPTION( FLT_OVERFLOW )
  613. EXCEPTION( FLT_STACK_CHECK )
  614. EXCEPTION( FLT_UNDERFLOW )
  615. EXCEPTION( INT_DIVIDE_BY_ZERO )
  616. EXCEPTION( INT_OVERFLOW )
  617. EXCEPTION( PRIV_INSTRUCTION )
  618. EXCEPTION( IN_PAGE_ERROR )
  619. EXCEPTION( ILLEGAL_INSTRUCTION )
  620. EXCEPTION( NONCONTINUABLE_EXCEPTION )
  621. EXCEPTION( STACK_OVERFLOW )
  622. EXCEPTION( INVALID_DISPOSITION )
  623. EXCEPTION( GUARD_PAGE )
  624. EXCEPTION( INVALID_HANDLE )
  625. }
  626. static CHAR szBuffer[512] = { 0 };
  627. FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
  628. GetModuleHandle( "NTDLL.DLL" ),
  629. dwCode, 0, szBuffer, sizeof( szBuffer ), 0 );
  630. return szBuffer;
  631. }
  632. static BOOL GetLogicalAddress( PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset )
  633. {
  634. szModule[0] = 0;
  635. section = 0;
  636. offset = 0;
  637. if ((unsigned)(memsize_t)addr<0x10000)
  638. return FALSE;
  639. MEMORY_BASIC_INFORMATION mbi;
  640. if ( !VirtualQuery( addr, &mbi, sizeof(mbi) ) )
  641. return FALSE;
  642. memsize_t hMod = (memsize_t)mbi.AllocationBase;
  643. if ( !GetModuleFileName( (HMODULE)hMod, szModule, len ) )
  644. return FALSE;
  645. PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
  646. PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew);
  647. PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr );
  648. memsize_t rva = (memsize_t)addr - hMod;
  649. for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++ )
  650. {
  651. DWORD sectionStart = pSection->VirtualAddress;
  652. DWORD sectionEnd = sectionStart
  653. + std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize);
  654. if ( (rva >= sectionStart) && (rva <= sectionEnd) )
  655. {
  656. section = i+1;
  657. offset = (DWORD)(rva - sectionStart);
  658. return TRUE;
  659. }
  660. }
  661. return FALSE;
  662. }
  663. #if defined(_WIN32)
  664. #ifdef __cplusplus
  665. extern "C" {
  666. typedef BOOL (CALLBACK* LPENUMPROCESSMODULES)(HANDLE,HMODULE *,DWORD,LPDWORD);
  667. typedef BOOL (CALLBACK* LPGETMODULEINFORMATION)(HANDLE,HMODULE,LPMODULEINFO,DWORD);
  668. }
  669. #endif
  670. #endif
  671. static void ModuleWalk()
  672. {
  673. HMODULE hmSystem = LoadLibrary("psapi.dll");
  674. if (!hmSystem)
  675. return;
  676. LPENUMPROCESSMODULES enumProcessModules = (LPENUMPROCESSMODULES)GetProcAddress(hmSystem,"EnumProcessModules");
  677. if (!enumProcessModules)
  678. return;
  679. LPGETMODULEINFORMATION getModuleInformation = (LPGETMODULEINFORMATION)GetProcAddress(hmSystem,"GetModuleInformation");
  680. if (!getModuleInformation)
  681. return;
  682. DWORD processID = GetCurrentProcessId();
  683. DBGLOG("Process ID: %u", processID);
  684. // Get a list of all the modules in this process.
  685. HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
  686. PROCESS_VM_READ,
  687. FALSE, processID );
  688. if (NULL == hProcess)
  689. return;
  690. HMODULE hMods[1024];
  691. DWORD cbNeeded;
  692. if (enumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
  693. for (unsigned i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ ) {
  694. char szModName[MAX_PATH];
  695. szModName[0] = 0;
  696. // Get the full path to the module's file.
  697. MODULEINFO modinfo;
  698. memset(&modinfo,0,sizeof(modinfo));
  699. getModuleInformation(hProcess, hMods[i], &modinfo, sizeof(modinfo));
  700. GetModuleFileName( hMods[i], szModName, sizeof(szModName));
  701. IERRLOG("%8X %8X %8X %s",(unsigned)modinfo.lpBaseOfDll,(unsigned)modinfo.SizeOfImage,(unsigned)modinfo.EntryPoint,szModName);
  702. }
  703. }
  704. CloseHandle( hProcess );
  705. FreeLibrary(hmSystem);
  706. }
  707. static void StackWalk( size_t pc, size_t bp )
  708. {
  709. IERRLOG( "Call stack:" );
  710. IERRLOG( "Address Frame Logical addr Module" );
  711. size_t * pFrame;
  712. size_t * pPrevFrame=NULL;
  713. pFrame = (size_t*)bp;
  714. do
  715. {
  716. TCHAR szModule[MAX_PATH] = "";
  717. DWORD section = 0, offset = 0;
  718. if (pc>0x10000)
  719. GetLogicalAddress((PVOID)pc, szModule,sizeof(szModule),section,offset );
  720. else
  721. strcpy(szModule,"NULL");
  722. IERRLOG( "%08X %08X %04X:%08X %s",
  723. pc, pFrame, section, offset, szModule );
  724. if ( (size_t)pFrame & 0x80000003 )
  725. break;
  726. if ( (size_t)pFrame <= (size_t)pPrevFrame )
  727. break;
  728. if ( IsBadWritePtr(pFrame, sizeof(PVOID)*2) )
  729. break;
  730. pc = pFrame[1];
  731. if ( IsBadCodePtr((FARPROC) pc) )
  732. break;
  733. pPrevFrame = pFrame;
  734. pFrame = (size_t *)pFrame[0];
  735. } while ( 1 );
  736. }
  737. static void doPrintStackReport( size_t ip, size_t _bp, size_t sp )
  738. {
  739. if (_bp==0) {
  740. #ifdef _ARCH_X86_
  741. __asm {
  742. mov eax,ebp
  743. mov _bp,eax
  744. }
  745. #else
  746. IERRLOG("inline assembler is only supported for x86_32; StackReport incomplete bp tend to not be used");
  747. #endif
  748. }
  749. for (unsigned i=0;i<8;i++) {
  750. StringBuffer s;
  751. #ifdef __64BIT__
  752. s.appendf("Stack[%016X]:",sp);
  753. #else
  754. s.appendf("Stack[%08X]:",sp);
  755. #endif
  756. for (unsigned j=0;j<8;j++) {
  757. if ( IsBadReadPtr((const void *)sp, sizeof(unsigned)) )
  758. break;
  759. size_t v = *(size_t *)sp;
  760. sp += sizeof(unsigned);
  761. #ifdef __64BIT__
  762. s.appendf(" %016X",v);
  763. #else
  764. s.appendf(" %08X",v);
  765. #endif
  766. }
  767. IERRLOG( "%s",s.str());
  768. }
  769. StackWalk( ip , _bp);
  770. ModuleWalk();
  771. StringBuffer threadlist;
  772. IERRLOG( "ThreadList:\n%s",getThreadList(threadlist).str());
  773. }
  774. static void PrintExceptionReport( PEXCEPTION_POINTERS pExceptionInfo)
  775. {
  776. IERRLOG("=====================================================");
  777. PrintMemoryStatusLog();
  778. PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
  779. IERRLOG( "Exception code: %08X %s",
  780. pExceptionRecord->ExceptionCode,
  781. GetExceptionString(pExceptionRecord->ExceptionCode) );
  782. IERRLOG( "Fault address: %08X", pExceptionRecord->ExceptionAddress);
  783. TCHAR szFaultingModule[MAX_PATH];
  784. DWORD section, offset;
  785. GetLogicalAddress( pExceptionRecord->ExceptionAddress,
  786. szFaultingModule,
  787. sizeof( szFaultingModule ),
  788. section, offset );
  789. IERRLOG("Fault module: %02X:%08X %s", section, offset, szFaultingModule);
  790. PCONTEXT pCtx = pExceptionInfo->ContextRecord;
  791. IERRLOG( "\nRegisters:" );
  792. #ifdef _ARCH_X86_64_
  793. IERRLOG("RAX:%016" I64F "X RBX:%016" I64F "X RCX:%016" I64F "X RDX:%016" I64F "X RSI:%016" I64F "X RDI:%016" I64F "X",
  794. pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, pCtx->Rsi, pCtx->Rdi );
  795. IERRLOG("R8: %016" I64F "X R9: %016" I64F "X R10:%016" I64F "X R11:%016" I64F "X R12:%016" I64F "X R13:%016" I64F "X",
  796. pCtx->R8, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13);
  797. IERRLOG("R14:%016" I64F "X R15:%016" I64F "X",
  798. pCtx->R14, pCtx->R15);
  799. IERRLOG( "CS:RIP:%04X:%016" I64F "X", pCtx->SegCs, pCtx->Rip );
  800. IERRLOG( "SS:PSP:%04X:%016" I64F "X PBP:%016" I64F "X",
  801. pCtx->SegSs, pCtx->Rsp, pCtx->Rbp );
  802. #elif defined(_ARCH_X86_)
  803. IERRLOG("EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X",
  804. pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, pCtx->Esi, pCtx->Edi );
  805. IERRLOG( "CS:EIP:%04X:%08X", pCtx->SegCs, pCtx->Eip );
  806. IERRLOG( "SS:ESP:%04X:%08X EBP:%08X",
  807. pCtx->SegSs, pCtx->Esp, pCtx->Ebp );
  808. #else
  809. // ARMFIX: Implement register bank dump for ARM on _WIN32.
  810. IERRLOG("Register bank not implemented for your platform");
  811. #endif
  812. IERRLOG( "DS:%04X ES:%04X FS:%04X GS:%04X",
  813. pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs );
  814. IERRLOG( "Flags:%08X", pCtx->EFlags );
  815. #ifdef _ARCH_X86_64_
  816. doPrintStackReport(pCtx->Rip, pCtx->Rbp,pCtx->Rsp);
  817. #elif defined(_ARCH_X86_)
  818. doPrintStackReport(pCtx->Eip, pCtx->Ebp,pCtx->Esp);
  819. #else
  820. // ARMFIX: Implement stack dump for ARM on _WIN32.
  821. IERRLOG("Stack report not implemented for your platform");
  822. #endif
  823. if (SEHtermOnSystemDLLs || SEHtermAlways) {
  824. char *s = szFaultingModule;
  825. while (*s) {
  826. char *sep = strchr(s,'\\');
  827. if (!sep) {
  828. sep = strchr(s,'.');
  829. if (sep)
  830. *sep = 0;
  831. break;
  832. }
  833. s = sep+1;
  834. }
  835. if (SEHtermAlways || (stricmp(s,"ntdll")==0)||(stricmp(s,"kernel32")==0)||(stricmp(s,"msvcrt")==0)||(stricmp(s,"msvcrtd")==0)) {
  836. TerminateProcess(GetCurrentProcess(), 1);
  837. }
  838. }
  839. }
  840. class jlib_thrown_decl CSEHException: public ISEH_Exception, public CInterface
  841. {
  842. public:
  843. IMPLEMENT_IINTERFACE;
  844. CSEHException(unsigned int u, _EXCEPTION_POINTERS* pExp) : errcode((int)u)
  845. {
  846. #ifdef EXTENDED_EXCEPTION_TRACE
  847. PrintExceptionReport(pExp);
  848. #endif
  849. #ifdef ALLREGS
  850. char s[256]; // not too good on stack faults!
  851. sprintf(s,"SEH Exception(%x)\n"
  852. "EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X\n"
  853. "EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X\n"
  854. "CS=%04X DS=%04X SS=%04X ES=%04X FS=%04X GS=%04X",
  855. u,
  856. pExp->ContextRecord->Eax, pExp->ContextRecord->Ebx,
  857. pExp->ContextRecord->Ecx, pExp->ContextRecord->Edx,
  858. pExp->ContextRecord->Esi, pExp->ContextRecord->Edi,
  859. pExp->ContextRecord->Ebp, pExp->ContextRecord->Esp,
  860. pExp->ContextRecord->Eip, pExp->ContextRecord->EFlags,
  861. pExp->ContextRecord->SegCs, pExp->ContextRecord->SegDs,
  862. pExp->ContextRecord->SegSs, pExp->ContextRecord->SegEs,
  863. pExp->ContextRecord->SegFs, pExp->ContextRecord->SegGs);
  864. #else
  865. char s[80];
  866. #ifdef _ARCH_X86_64_
  867. sprintf(s,"SEH Exception(%08X) at %04X:%016" I64F "X\n",u,pExp->ContextRecord->SegCs,pExp->ContextRecord->Rip);
  868. #elif defined(_ARCH_X86_)
  869. sprintf(s,"SEH Exception(%08X) at %04X:%08X\n",u,pExp->ContextRecord->SegCs,pExp->ContextRecord->Eip);
  870. #else
  871. // ARMFIX: Implement exception dump for ARM on _WIN32.
  872. sprintf(s,"SEH Exception");
  873. #endif
  874. #endif
  875. msg.set(s);
  876. };
  877. int errorCode() const { return errcode; }
  878. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  879. MessageAudience errorAudience() const { return MSGAUD_user; }
  880. static void Translate(unsigned int u, _EXCEPTION_POINTERS* pExp)
  881. {
  882. #ifdef _DEBUG
  883. if (u == 0x80000003) return; // int 3 breakpoints
  884. static CriticalSection crit;
  885. {
  886. CriticalBlock b(crit);
  887. PrintExceptionReport(pExp);
  888. }
  889. #endif
  890. ISEH_Exception *e = new CSEHException(u,pExp);
  891. if (SEHHandler && SEHHandler->fireException(e)) return;
  892. throw(e);
  893. }
  894. protected:
  895. int errcode;
  896. StringAttr msg;
  897. };
  898. #endif
  899. #else
  900. #ifdef LINUX_SIGNAL_EXCEPTION
  901. #ifndef NO_LINUX_SEH
  902. static IException *sigsegv_exc;
  903. #endif
  904. static int excsignal;
  905. class jlib_thrown_decl CSEHException: public ISEH_Exception, public CInterface
  906. {
  907. public:
  908. IMPLEMENT_IINTERFACE;
  909. CSEHException(int signum, const char *s)
  910. {
  911. errcode = signum;
  912. msg.set(s);
  913. };
  914. int errorCode() const { return errcode; }
  915. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  916. MessageAudience errorAudience() const { return MSGAUD_user; }
  917. protected:
  918. int errcode;
  919. StringAttr msg;
  920. };
  921. #ifndef NO_LINUX_SEH
  922. static void throwSigSegV()
  923. {
  924. int childpid = fork();
  925. if (childpid <= 0) { // the child
  926. // generate a coredump on different process
  927. signal(excsignal, SIG_DFL);
  928. raise(excsignal);
  929. return;
  930. }
  931. PROGLOG("Dumping core using child process %d",childpid);
  932. waitpid(childpid, NULL, 0);
  933. if (SEHHandler && SEHHandler->fireException(sigsegv_exc))
  934. return;
  935. throw sigsegv_exc;
  936. }
  937. #endif
  938. NO_SANITIZE("alignment") void excsighandler(int signum, siginfo_t *info, void *extra)
  939. {
  940. static byte nested=0;
  941. if (nested++)
  942. return;
  943. excsignal = 0;
  944. #if defined(NO_LINUX_SEH)
  945. // ensure other signals from now on cause exit
  946. sigset_t blockset;
  947. sigemptyset(&blockset);
  948. struct sigaction act;
  949. act.sa_mask = blockset;
  950. act.sa_flags = 0;
  951. act.sa_handler = SIG_DFL;
  952. sigaction(SIGSEGV, &act, NULL);
  953. sigaction(SIGILL, &act, NULL);
  954. sigaction(SIGBUS, &act, NULL);
  955. sigaction(SIGFPE, &act, NULL);
  956. sigaction(SIGABRT, &act, NULL);
  957. #endif
  958. StringBuffer s;
  959. #ifdef _ARCH_X86_64_
  960. #define I64X "%016" I64F "X"
  961. ucontext_t *uc = (ucontext_t *)extra;
  962. #ifdef __APPLE__
  963. __int64 ip = uc->uc_mcontext->__ss.__rip;
  964. __int64 sp = uc->uc_mcontext->__ss.__rsp;
  965. #else
  966. __int64 ip = uc->uc_mcontext.gregs[REG_RIP];
  967. __int64 sp = uc->uc_mcontext.gregs[REG_RSP];
  968. #endif
  969. excsignal = signum;
  970. s.appendf("SIG: %s(%d), accessing " I64X ", IP=" I64X, strsignal(signum),signum, (__int64)info->si_addr, ip);
  971. StringBuffer networkIp;
  972. PROGLOG("================================================");
  973. PROGLOG("Program: %s:%s", queryHostIP().getIpText(networkIp).str(),queryCurrentProcessPath());
  974. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  975. PROGLOG("Fault IP: " I64X "", ip);
  976. PROGLOG("Accessing: " I64X "", (unsigned __int64) info->si_addr);
  977. #ifdef _EXECINFO_H
  978. printStackReport(ip);
  979. #endif
  980. PROGLOG("Registers:" );
  981. #ifdef __APPLE__
  982. PROGLOG("EAX:" I64X " EBX:" I64X " ECX:" I64X " EDX:" I64X " ESI:" I64X " EDI:" I64X "",
  983. (unsigned __int64) uc->uc_mcontext->__ss.__rax, (unsigned __int64)uc->uc_mcontext->__ss.__rbx,
  984. (unsigned __int64) uc->uc_mcontext->__ss.__rcx, (unsigned __int64)uc->uc_mcontext->__ss.__rdx,
  985. (unsigned __int64) uc->uc_mcontext->__ss.__rsi, (unsigned __int64)uc->uc_mcontext->__ss.__rdi);
  986. PROGLOG("R8 :" I64X " R9 :" I64X " R10:" I64X " R11:" I64X "",
  987. (unsigned __int64) uc->uc_mcontext->__ss.__r8, (unsigned __int64)uc->uc_mcontext->__ss.__r9,
  988. (unsigned __int64) uc->uc_mcontext->__ss.__r10, (unsigned __int64) uc->uc_mcontext->__ss.__r11 );
  989. PROGLOG("R12:" I64X " R13:" I64X " R14:" I64X " R15:" I64X "",
  990. (unsigned __int64) uc->uc_mcontext->__ss.__r12, (unsigned __int64)uc->uc_mcontext->__ss.__r13,
  991. (unsigned __int64) uc->uc_mcontext->__ss.__r14, (unsigned __int64) uc->uc_mcontext->__ss.__r15 );
  992. PROGLOG( "CS:EIP:%04X:" I64X "", ((unsigned) uc->uc_mcontext->__ss.__cs)&0xffff, ip );
  993. PROGLOG( " ESP:" I64X " EBP:" I64X "", sp, (unsigned __int64) uc->uc_mcontext->__ss.__rbp );
  994. #else
  995. PROGLOG("EAX:" I64X " EBX:" I64X " ECX:" I64X " EDX:" I64X " ESI:" I64X " EDI:" I64X "",
  996. (unsigned __int64) uc->uc_mcontext.gregs[REG_RAX], (unsigned __int64)uc->uc_mcontext.gregs[REG_RBX],
  997. (unsigned __int64) uc->uc_mcontext.gregs[REG_RCX], (unsigned __int64) uc->uc_mcontext.gregs[REG_RDX],
  998. (unsigned __int64) uc->uc_mcontext.gregs[REG_RSI], (unsigned __int64) uc->uc_mcontext.gregs[REG_RDI] );
  999. PROGLOG("R8 :" I64X " R9 :" I64X " R10:" I64X " R11:" I64X "",
  1000. (unsigned __int64) uc->uc_mcontext.gregs[REG_R8], (unsigned __int64)uc->uc_mcontext.gregs[REG_R9],
  1001. (unsigned __int64) uc->uc_mcontext.gregs[REG_R10], (unsigned __int64) uc->uc_mcontext.gregs[REG_R11] );
  1002. PROGLOG("R12:" I64X " R13:" I64X " R14:" I64X " R15:" I64X "",
  1003. (unsigned __int64) uc->uc_mcontext.gregs[REG_R12], (unsigned __int64)uc->uc_mcontext.gregs[REG_R13],
  1004. (unsigned __int64) uc->uc_mcontext.gregs[REG_R14], (unsigned __int64) uc->uc_mcontext.gregs[REG_R15] );
  1005. PROGLOG( "CS:EIP:%04X:" I64X "", ((unsigned) uc->uc_mcontext.gregs[REG_CSGSFS])&0xffff, ip );
  1006. PROGLOG( " ESP:" I64X " EBP:" I64X "", sp, (unsigned __int64) uc->uc_mcontext.gregs[REG_RBP] );
  1007. #endif
  1008. for (unsigned i=0;i<8;i++) {
  1009. StringBuffer s;
  1010. s.appendf("Stack[" I64X "]:",sp);
  1011. for (unsigned j=0;j<8;j++) {
  1012. __int64 v = *(size_t *)sp;
  1013. sp += sizeof(unsigned);
  1014. s.appendf(" " I64X "",v);
  1015. }
  1016. PROGLOG( "%s",s.str());
  1017. }
  1018. #elif defined (__linux__) && defined (_ARCH_X86_)
  1019. ucontext_t *uc = (ucontext_t *)extra;
  1020. unsigned ip = uc->uc_mcontext.gregs[REG_EIP];
  1021. unsigned sp = uc->uc_mcontext.gregs[REG_ESP];
  1022. excsignal = signum;
  1023. s.appendf("SIG: %s(%d), accessing %p, IP=%x", strsignal(signum),signum, info->si_addr, ip);
  1024. StringBuffer networkIp;
  1025. PROGLOG("================================================");
  1026. PROGLOG("Program: %s:%s", queryHostIP().getIpText(networkIp).str(),queryCurrentProcessPath());
  1027. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  1028. PROGLOG("Fault IP: %08X", ip);
  1029. PROGLOG("Accessing: %08X", (unsigned) info->si_addr);
  1030. #ifdef _EXECINFO_H
  1031. printStackReport(ip);
  1032. #endif
  1033. PROGLOG("Registers:" );
  1034. PROGLOG("EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X",
  1035. uc->uc_mcontext.gregs[REG_EAX], uc->uc_mcontext.gregs[REG_EBX],
  1036. uc->uc_mcontext.gregs[REG_ECX], uc->uc_mcontext.gregs[REG_EDX],
  1037. uc->uc_mcontext.gregs[REG_ESI], uc->uc_mcontext.gregs[REG_EDI] );
  1038. PROGLOG( "CS:EIP:%04X:%08X", uc->uc_mcontext.gregs[REG_CS], ip );
  1039. PROGLOG( "SS:ESP:%04X:%08X EBP:%08X",
  1040. uc->uc_mcontext.gregs[REG_SS], sp, uc->uc_mcontext.gregs[REG_EBP] );
  1041. for (unsigned i=0;i<8;i++) {
  1042. StringBuffer s;
  1043. s.appendf("Stack[%08X]:",sp);
  1044. for (unsigned j=0;j<8;j++) {
  1045. size_t v = *(size_t *)sp;
  1046. sp += sizeof(unsigned);
  1047. s.appendf(" %08X",v);
  1048. }
  1049. PROGLOG( "%s",s.str());
  1050. }
  1051. PROGLOG("Frame:");
  1052. unsigned* bp = (unsigned*) (uc->uc_mcontext.gregs[REG_EBP]);
  1053. for (unsigned n=0; n<64; n++) {
  1054. unsigned * nextbp = (unsigned *) *bp++;
  1055. unsigned fip = *bp;
  1056. if ((fip < 0x08000000) || (fip > 0x7fffffff) || (nextbp < bp))
  1057. break;
  1058. PROGLOG("%2d %08X %08X",n+1,fip,(unsigned) bp);
  1059. bp = nextbp;
  1060. }
  1061. #elif defined (__linux__) && defined (__ARM_ARCH_7A__)
  1062. #pragma message "Implement signal dump for ARMv7-A."
  1063. ucontext_t *uc = (ucontext_t *) extra;
  1064. PROGLOG("================================================");
  1065. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  1066. PROGLOG("Registers:" );
  1067. PROGLOG("r0 :%08lX r1 :%08lX r2 :%08lX r3 :%08lX r4 :%08lX r5 :%08lX",
  1068. uc->uc_mcontext.arm_r0, uc->uc_mcontext.arm_r1, uc->uc_mcontext.arm_r2,
  1069. uc->uc_mcontext.arm_r3, uc->uc_mcontext.arm_r4, uc->uc_mcontext.arm_r5);
  1070. PROGLOG("r6 :%08lX r7 :%08lX r8 :%08lX r9 :%08lX r10:%08lX fp :%08lX",
  1071. uc->uc_mcontext.arm_r6, uc->uc_mcontext.arm_r7, uc->uc_mcontext.arm_r8,
  1072. uc->uc_mcontext.arm_r9, uc->uc_mcontext.arm_r10, uc->uc_mcontext.arm_fp);
  1073. PROGLOG("ip :%08lX sp :%08lX lr :%08lX pc :%08lX",
  1074. uc->uc_mcontext.arm_ip, uc->uc_mcontext.arm_sp, uc->uc_mcontext.arm_lr,
  1075. uc->uc_mcontext.arm_pc);
  1076. PROGLOG("CPSR:%08lX\n", uc->uc_mcontext.arm_cpsr);
  1077. struct flags
  1078. {
  1079. unsigned int Mode:4; // bit 0 - 3
  1080. unsigned int M:1; // bit 4
  1081. unsigned int T:1; // bit 5
  1082. unsigned int F:1; // bit 6
  1083. unsigned int I:1; // bit 7
  1084. unsigned int A:1; // bit 8
  1085. unsigned int E:1; // bit 9
  1086. unsigned int IT1:6; // bit 10 - 15
  1087. unsigned int GE:4; // bit 16 - 19
  1088. unsigned int DNM:4; // bit 20 - 23
  1089. unsigned int J:1; // bit 24
  1090. unsigned int IT2:2; // bit 25 - 26
  1091. unsigned int Q:1; // bit 27
  1092. unsigned int V:1; // bit 28
  1093. unsigned int C:1; // bit 29
  1094. unsigned int Z:1; // bit 30
  1095. unsigned int N:1; // bit 31
  1096. } *flags_p;
  1097. const char *ArmCpuModes[] = {
  1098. // M M[3:0]
  1099. "User", // 1 0000
  1100. "FIQ", // 1 0001
  1101. "IRQ", // 1 0010
  1102. "Supervisor", // 1 0011
  1103. "N/A", // 1 0100
  1104. "N/A", // 1 0101
  1105. "Monitor", // 1 0110
  1106. "Abort", // 1 0111
  1107. "N/A", // 1 1000
  1108. "N/A", // 1 1001
  1109. "Hyp" // 1 1010
  1110. "Undefined", // 1 1011
  1111. "N/A", // 1 1100
  1112. "N/A", // 1 1101
  1113. "N/A", // 1 1110
  1114. "System" // 1 1111
  1115. };
  1116. flags_p = (struct flags *)&uc->uc_mcontext.arm_cpsr;
  1117. PROGLOG("Flags N:%d Z:%d C:%d V:%d Q:%d IT:0x%X J:%d GE:0x%X E:%d A:%d I:%d F:%d T:%d M:0x%X [%s]"
  1118. , flags_p->N, flags_p->Z, flags_p->C, flags_p->V, flags_p->Q
  1119. , (flags_p->IT2 << 6 | flags_p->IT1)
  1120. , flags_p->J, flags_p->GE
  1121. , flags_p->E, flags_p->A, flags_p->I, flags_p->F, flags_p->T, (flags_p->M << 4 | flags_p->Mode)
  1122. , ArmCpuModes[flags_p->Mode]
  1123. );
  1124. PROGLOG("Fault address: %08lX", uc->uc_mcontext.fault_address);
  1125. PROGLOG("Trap no : %08lX", uc->uc_mcontext.trap_no);
  1126. PROGLOG("Error code : %08lX", uc->uc_mcontext.error_code);
  1127. PROGLOG("Old mask : %08lX", uc->uc_mcontext.oldmask);
  1128. unsigned sp = uc->uc_mcontext.arm_sp;
  1129. for (unsigned i=0;i<8;i++)
  1130. {
  1131. StringBuffer s;
  1132. s.appendf("Stack[%08X]:",sp);
  1133. for (unsigned j=0;j<8;j++)
  1134. {
  1135. size_t v = *(size_t *)sp;
  1136. sp += sizeof(unsigned);
  1137. s.appendf(" %08X",v);
  1138. }
  1139. }
  1140. PROGLOG( "%s",s.str());
  1141. #elif defined (__linux__) && defined (__arm__)
  1142. #pragma message "Unknown ARM architecture!"
  1143. PROGLOG("================================================");
  1144. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  1145. PROGLOG("More information unavailable on your platform");
  1146. #else
  1147. // Placeholder for any new HW-SW platform
  1148. #endif
  1149. StringBuffer threadlist;
  1150. PROGLOG( "ThreadList:\n%s",getThreadList(threadlist).str());
  1151. queryLogMsgManager()->flushQueue(10*1000);
  1152. // MCK - really should not return after recv'ing any of these signals
  1153. #ifndef NO_LINUX_SEH
  1154. void (* _P)() = throwSigSegV;
  1155. uc->uc_mcontext.gregs[REG_ESP]-=4;
  1156. uc->uc_mcontext.gregs[REG_EIP] = (unsigned)_P;
  1157. unsigned *spp = (unsigned *)sp;
  1158. *spp = ip;
  1159. sigsegv_exc = new CSEHException(signum,s.str());
  1160. #else
  1161. if (SEHHandler)
  1162. {
  1163. if ( SEHHandler->fireException(new CSEHException(signum,s.str())) )
  1164. return;
  1165. }
  1166. raise(signum);
  1167. #endif
  1168. nested--;
  1169. }
  1170. #endif
  1171. #endif
  1172. void jlib_decl setTerminateOnSEHInSystemDLLs(bool set)
  1173. {
  1174. SEHtermOnSystemDLLs = set;
  1175. }
  1176. void jlib_decl setTerminateOnSEH(bool set)
  1177. {
  1178. SEHtermAlways = set;
  1179. }
  1180. void *EnableSEHtranslation()
  1181. {
  1182. #ifdef NOSEH
  1183. return NULL;
  1184. #else
  1185. #ifdef _WIN32
  1186. return _set_se_translator( CSEHException::Translate );
  1187. #else
  1188. UNIMPLEMENTED;
  1189. #endif
  1190. #endif
  1191. }
  1192. void jlib_decl *setSEHtoExceptionHandler(IExceptionHandler *handler)
  1193. {
  1194. #ifdef NOSEH
  1195. return NULL;
  1196. #endif
  1197. void *ret = SEHHandler;
  1198. SEHHandler = handler;
  1199. return ret;
  1200. }
  1201. void jlib_decl enableSEHtoExceptionMapping()
  1202. {
  1203. #ifdef NOSEH
  1204. return;
  1205. #endif
  1206. if (SEHnested++)
  1207. return; // already done
  1208. #ifdef _WIN32
  1209. enableThreadSEH();
  1210. SEHrestore = EnableSEHtranslation();
  1211. #else
  1212. struct sigaction act;
  1213. sigset_t blockset;
  1214. sigemptyset(&blockset);
  1215. // defer these for thread in handler
  1216. sigaddset(&blockset, SIGINT);
  1217. sigaddset(&blockset, SIGQUIT);
  1218. sigaddset(&blockset, SIGTERM);
  1219. act.sa_mask = blockset;
  1220. act.sa_flags = SA_SIGINFO;
  1221. #if defined(SA_RESETHAND)
  1222. act.sa_flags |= SA_RESETHAND;
  1223. #endif
  1224. act.sa_sigaction = &excsighandler;
  1225. sigaction(SIGSEGV, &act, NULL);
  1226. #ifndef _DEBUG
  1227. sigaction(SIGILL, &act, NULL);
  1228. #endif
  1229. sigaction(SIGBUS, &act, NULL);
  1230. sigaction(SIGFPE, &act, NULL);
  1231. sigaction(SIGABRT, &act, NULL);
  1232. #endif
  1233. }
  1234. void jlib_decl disableSEHtoExceptionMapping()
  1235. {
  1236. #ifdef NOSEH
  1237. return;
  1238. #endif
  1239. if (--SEHnested)
  1240. return;
  1241. #ifdef _WIN32
  1242. if (SEHrestore) {
  1243. void *restore = SEHrestore;
  1244. SEHrestore = NULL;
  1245. _set_se_translator( (_se_translator_function)restore );
  1246. }
  1247. #else
  1248. sigset_t blockset;
  1249. sigemptyset(&blockset);
  1250. struct sigaction act;
  1251. act.sa_mask = blockset;
  1252. act.sa_flags = 0;
  1253. act.sa_handler = SIG_DFL;
  1254. sigaction(SIGSEGV, &act, NULL);
  1255. sigaction(SIGILL, &act, NULL);
  1256. sigaction(SIGBUS, &act, NULL);
  1257. sigaction(SIGFPE, &act, NULL);
  1258. sigaction(SIGABRT, &act, NULL);
  1259. #endif
  1260. }
  1261. StringBuffer & formatSystemError(StringBuffer & out, unsigned errcode)
  1262. {
  1263. #ifdef _WIN32
  1264. const char * lpMessageBuffer=NULL;
  1265. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1266. NULL,
  1267. errcode,
  1268. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default
  1269. (LPTSTR) &lpMessageBuffer,
  1270. 0,
  1271. NULL );
  1272. if (lpMessageBuffer) {
  1273. out.append(lpMessageBuffer);
  1274. LocalFree( (void *)lpMessageBuffer );
  1275. }
  1276. else {
  1277. out.append(errcode);
  1278. }
  1279. #else
  1280. int saverr = errno;
  1281. errno = 0;
  1282. const char *errstr = strerror(errcode);
  1283. if (errno==0) {
  1284. out.append(errstr);
  1285. }
  1286. else {
  1287. out.append(errcode);
  1288. }
  1289. errno = saverr;
  1290. #endif
  1291. return out;
  1292. }
  1293. IException * deserializeException(MemoryBuffer & in)
  1294. {
  1295. byte nulle;
  1296. in.read(nulle);
  1297. if (nulle) return NULL;
  1298. int code;
  1299. StringAttr text;
  1300. in.read(code);
  1301. in.read(text);
  1302. return makeStringExceptionV(code, "%s", text.get());
  1303. }
  1304. void jlib_decl serializeException(IException * e, MemoryBuffer & out)
  1305. {
  1306. if (!e)
  1307. out.append((byte)1);
  1308. else
  1309. {
  1310. out.append((byte)0);
  1311. StringBuffer text;
  1312. out.append(e->errorCode());
  1313. out.append(e->errorMessage(text).str());
  1314. }
  1315. }
  1316. void printStackReport(__int64 startIP)
  1317. {
  1318. if (!queryLogMsgManager())
  1319. return;
  1320. #ifdef _WIN32
  1321. unsigned onstack=1234;
  1322. doPrintStackReport(0, 0,(unsigned)&onstack);
  1323. #elif defined(__linux__)
  1324. DBGLOG("Backtrace:");
  1325. void *btarray[100];
  1326. unsigned btn = backtrace (btarray, 100);
  1327. char **strings = backtrace_symbols (btarray, btn);
  1328. unsigned i;
  1329. unsigned firstReal = 0;
  1330. if (startIP)
  1331. {
  1332. VStringBuffer iptext("[%p]", (void *) startIP);
  1333. for (i=0; i<btn; i++)
  1334. {
  1335. if (strstr(strings[i], iptext) != nullptr)
  1336. {
  1337. firstReal = i;
  1338. break;
  1339. }
  1340. }
  1341. }
  1342. for (i=firstReal; i<btn; i++)
  1343. DBGLOG(" %s", strings[i]);
  1344. free (strings);
  1345. #endif
  1346. queryLogMsgManager()->flushQueue(10*1000);
  1347. }
  1348. //---------------------------------------------------------------------------------------------------------------------
  1349. unsigned getCommandOutput(StringBuffer &output, const char *cmd, const char *cmdTitle, const char *allowedPrograms)
  1350. {
  1351. Owned<IPipeProcess> pipe = createPipeProcess(allowedPrograms);
  1352. if (pipe->run(cmdTitle, cmd, nullptr, false, true, false))
  1353. {
  1354. Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
  1355. readSimpleStream(output, *pipeReader);
  1356. }
  1357. return pipe->wait();
  1358. }
  1359. //---------------------------------------------------------------------------------------------------------------------
  1360. bool getDebuggerGetStacksCmd(StringBuffer &output)
  1361. {
  1362. #ifndef __linux__
  1363. return false; // unsupported
  1364. #endif
  1365. const char *exePath = queryCurrentProcessPath();
  1366. if (!exePath)
  1367. {
  1368. output.append("Unable to capture stacks");
  1369. return false;
  1370. }
  1371. return output.appendf("gdb --batch -n -ex 'thread apply all bt' %s %u", exePath, GetCurrentProcessId());
  1372. }
  1373. bool getAllStacks(StringBuffer &output)
  1374. {
  1375. StringBuffer cmd;
  1376. if (!getDebuggerGetStacksCmd(cmd))
  1377. return false;
  1378. return 0 == getCommandOutput(output, cmd, "get stacks");
  1379. }
  1380. //---------------------------------------------------------------------------------------------------------------------
  1381. class jlib_decl CError : public CInterfaceOf<IError>
  1382. {
  1383. public:
  1384. CError(WarnErrorCategory _category,ErrorSeverity _severity, int _no, const char* _msg, const char* _filename, int _lineno, int _column, int _position, unsigned _activity, const char * _scope);
  1385. virtual int errorCode() const override { return no; }
  1386. virtual StringBuffer & errorMessage(StringBuffer & ret) const override { return ret.append(msg); }
  1387. virtual MessageAudience errorAudience() const override { return MSGAUD_user; }
  1388. virtual const char* getFilename() const override { return filename; }
  1389. virtual WarnErrorCategory getCategory() const override { return category; }
  1390. virtual int getLine() const override { return lineno; }
  1391. virtual int getColumn() const override { return column; }
  1392. virtual int getPosition() const override { return position; }
  1393. virtual StringBuffer& toString(StringBuffer&) const override;
  1394. virtual ErrorSeverity getSeverity() const override { return severity; }
  1395. virtual IError * cloneSetSeverity(ErrorSeverity _severity) const override;
  1396. virtual unsigned getActivity() const override { return activity; }
  1397. virtual const char * queryScope() const override { return scope; }
  1398. virtual IPropertyTree * toTree() const override;
  1399. protected:
  1400. ErrorSeverity severity;
  1401. WarnErrorCategory category;
  1402. int no;
  1403. StringAttr msg;
  1404. StringAttr filename;
  1405. StringAttr scope;
  1406. int lineno;
  1407. int column;
  1408. int position;
  1409. unsigned activity;
  1410. };
  1411. CError::CError(WarnErrorCategory _category, ErrorSeverity _severity, int _no, const char* _msg, const char* _filename, int _lineno, int _column, int _position, unsigned _activity, const char * _scope)
  1412. : severity(_severity), category(_category), msg(_msg), filename(_filename), scope(_scope), activity(_activity)
  1413. {
  1414. no = _no;
  1415. lineno = _lineno;
  1416. column = _column;
  1417. position = _position;
  1418. }
  1419. StringBuffer& CError::toString(StringBuffer& buf) const
  1420. {
  1421. buf.append(filename);
  1422. if(lineno && column)
  1423. buf.append('(').append(lineno).append(',').append(column).append(')');
  1424. buf.append(" : ");
  1425. buf.append(no).append(": ").append(msg);
  1426. return buf;
  1427. }
  1428. IPropertyTree * CError::toTree() const
  1429. {
  1430. Owned<IPropertyTree> xml = createPTree("exception", ipt_fast);
  1431. xml->setPropInt("@severity", severity);
  1432. xml->setPropInt("@category", category);
  1433. xml->setPropInt("@code", no);
  1434. xml->setProp("@msg", msg);
  1435. xml->setProp("@filename", filename);
  1436. xml->setProp("@scope", scope);
  1437. if (lineno)
  1438. xml->setPropInt("@line", lineno);
  1439. if (column)
  1440. xml->setPropInt("@column", column);
  1441. if (position)
  1442. xml->setPropInt("@pos", position);
  1443. if (activity)
  1444. xml->setPropInt("@activity", activity);
  1445. return xml.getClear();
  1446. }
  1447. IError * CError::cloneSetSeverity(ErrorSeverity newSeverity) const
  1448. {
  1449. return new CError(category, newSeverity,
  1450. errorCode(), msg, filename,
  1451. getLine(), getColumn(), getPosition(), getActivity(), queryScope());
  1452. }
  1453. ErrorSeverity queryDefaultSeverity(WarnErrorCategory category)
  1454. {
  1455. if (category == CategoryError)
  1456. return SeverityFatal;
  1457. if (category == CategoryInformation)
  1458. return SeverityInformation;
  1459. if (category == CategoryMistake)
  1460. return SeverityError;
  1461. return SeverityWarning;
  1462. }
  1463. IError *createError(WarnErrorCategory category, ErrorSeverity severity, int errNo, const char *msg, const char * filename, int lineno, int column, int pos, unsigned activity, const char * scope)
  1464. {
  1465. return new CError(category,severity,errNo,msg,filename,lineno,column,pos, activity, scope);
  1466. }
  1467. IError *createError(WarnErrorCategory category, ErrorSeverity severity, int errNo, const char *msg, unsigned activity, const char * scope)
  1468. {
  1469. return new CError(category,severity,errNo,msg,nullptr, 0, 0, 0, activity, scope);
  1470. }
  1471. IError *createError(IPropertyTree * tree)
  1472. {
  1473. return new CError((WarnErrorCategory)tree->getPropInt("@category"),
  1474. (ErrorSeverity)tree->getPropInt("@severity"),
  1475. tree->getPropInt("@code"),
  1476. tree->queryProp("@msg"),
  1477. tree->queryProp("@filename"),
  1478. tree->getPropInt("@line"),
  1479. tree->getPropInt("@column"),
  1480. tree->getPropInt("@pos"),
  1481. tree->getPropInt("@activity"),
  1482. tree->queryProp("@scope"));
  1483. }
  1484. //---------------------------------------------------------------------------------------------------------------------
  1485. void IErrorReceiver::ThrowStringException(int code,const char *format, ...) const
  1486. {
  1487. va_list args;
  1488. va_start(args, format);
  1489. IException *ret = MakeStringExceptionVA(code, format, args);
  1490. va_end(args);
  1491. throw ret;
  1492. }
  1493. void IErrorReceiver::reportError(int errNo, const char *msg, const char *filename, int lineno, int column, int position)
  1494. {
  1495. Owned<IError> err = createError(errNo,msg,filename,lineno,column,position);
  1496. report(err);
  1497. }
  1498. void IErrorReceiver::reportWarning(WarnErrorCategory category, int warnNo, const char *msg, const char *filename, int lineno, int column, int position)
  1499. {
  1500. ErrorSeverity severity = queryDefaultSeverity(category);
  1501. Owned<IError> warn = createError(category, severity,warnNo,msg,filename,lineno,column,position);
  1502. report(warn);
  1503. }
  1504. //---------------------------------------------------------------------------------------------------------------------