Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTLog.cpp
Go to the documentation of this file.
1 /************************************************************
2 *
3 * OTLog.cpp
4 *
5 */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "stdafx.hpp"
134 
135 #include "OTLog.hpp"
136 #include "util/OTPaths.hpp"
137 #include "util/stacktrace.h"
138 #include "opentxs/core/Version.hpp"
139 
140 #include <mutex>
141 
142 #ifndef _WIN32
143 #include <cerrno>
144 #endif
145 #include <fstream>
146 #include <iostream>
147 
148 #ifdef _WIN32
149 #include <Shlobj.h>
150 #include <direct.h>
151 #else
152 #include <libgen.h>
153 #include <unistd.h>
154 #endif
155 
156 #ifdef __APPLE__
157 #include "TargetConditionals.h"
158 #endif
159 
160 #ifdef TARGET_OS_MAC
161 #include <mach-o/dyld.h>
162 #include <limits.h>
163 #endif
164 
165 #define LOG_DEQUE_SIZE 1024
166 
167 extern "C" {
168 
169 #ifdef _WIN32
170 
171 #include <sys/timeb.h>
172 
173 // For signal handling in Windows.
174 LONG Win32FaultHandler(struct _EXCEPTION_POINTERS* ExInfo);
175 void LogStackFrames(void* FaultAdress, char*);
176 
177 #else // else if NOT _WIN32
178 
179 // These added for the signal handling:
180 //
181 #ifndef _GNU_SOURCE
182 #define _GNU_SOURCE
183 #endif
184 
185 #ifndef __USE_GNU
186 #define __USE_GNU
187 #endif
188 
189 // This shitty apple section is for struct sigcontext for the signal handling.
190 #if defined(__APPLE__)
191 #ifndef _XOPEN_SOURCE
192 #define _XOPEN_SOURCE 600
193 #endif
194 // Fucking Apple!
195 struct sigcontext
196 {
197  // cppcheck-suppress unusedStructMember
198  int32_t eip;
199 };
200 #endif // defined __APPLE__
201 
202 #if defined(ANDROID)
203 
204 #ifndef ucontext_h_seen
205 #define ucontext_h_seen
206 
207 #include <asm/sigcontext.h> /* for sigcontext */
208 #include <asm/signal.h> /* for stack_t */
209 
210 typedef struct ucontext
211 {
212  uint64_t uc_flags;
213  struct ucontext* uc_link;
214  stack_t uc_stack;
215  struct sigcontext uc_mcontext;
216  uint64_t uc_sigmask;
217 } ucontext_t;
218 
219 #endif // ucontext_h_seen
220 
221 #else // Not ANDROID
222 #include <signal.h>
223 #include <ucontext.h>
224 #include <wordexp.h>
225 #include <execinfo.h>
226 #endif
227 
228 #include <sys/resource.h>
229 
230 //#endif
231 
232 #endif // not _WIN32
233 
234 #include <sys/stat.h>
235 } // extern C
236 
237 #ifdef ANDROID
238 #include <android/log.h>
239 #endif
240 
241 #define LOGFILE_PRE "log-"
242 #define LOGFILE_EXT ".log"
243 #define GLOBAL_LOGNAME "init"
244 #define GLOBAL_LOGFILE "init.log"
245 
246 // OTLog Static Variables and Constants.
247 
248 namespace opentxs
249 {
250 
251 OTLog* OTLog::pLogger = nullptr;
252 
253 const OTString OTLog::m_strVersion = OPENTXS_VERSION_STRING;
254 const OTString OTLog::m_strPathSeparator = "/";
255 
256 OTLOG_IMPORT OTLogStream otErr(-1); // logs using otErr << )
257 OTLOG_IMPORT OTLogStream otInfo(2); // logs using OTLog::vOutput(2)
258 OTLOG_IMPORT OTLogStream otOut(0); // logs using OTLog::vOutput(0)
259 OTLOG_IMPORT OTLogStream otWarn(1); // logs using OTLog::vOutput(1)
260 OTLOG_IMPORT OTLogStream otLog3(3); // logs using OTLog::vOutput(3)
261 OTLOG_IMPORT OTLogStream otLog4(4); // logs using OTLog::vOutput(4)
262 OTLOG_IMPORT OTLogStream otLog5(5); // logs using OTLog::vOutput(5)
263 
265  : std::ostream(this)
266  , logLevel(_logLevel)
267  , next(0)
268  , pBuffer(new char[1024])
269 {
270 }
271 
273 {
274  delete[] pBuffer;
275  pBuffer = nullptr;
276 }
277 
279 {
280  pBuffer[next++] = c;
281  if (c != '\n' && next < 1000) {
282  return 0;
283  }
284 
285  pBuffer[next++] = '\0';
286  next = 0;
287 
288  if (logLevel < 0) {
289  OTLog::Error(pBuffer);
290  return 0;
291  }
292 
293  OTLog::Output(logLevel, pBuffer);
294  return 0;
295 }
296 
297 // OTLog Init, must run this before using any OTLog function.
298 
299 // static
300 bool OTLog::Init(const OTString& strThreadContext, const int32_t& nLogLevel)
301 {
302  if (nullptr == pLogger) {
303  pLogger = new OTLog();
304  pLogger->m_bInitialized = false;
305  }
306 
307  if (strThreadContext.Compare(GLOBAL_LOGNAME)) return false;
308 
309  if (!pLogger->m_bInitialized) {
310  pLogger->logDeque = std::deque<OTString*>();
311  pLogger->m_strThreadContext = strThreadContext;
312 
313  pLogger->m_nLogLevel = nLogLevel;
314 
315  if (!strThreadContext.Exists() ||
316  strThreadContext.Compare("")) // global
317  {
318  pLogger->m_strLogFileName = GLOBAL_LOGFILE;
319  }
320  else // not global
321  {
322 
323  pLogger->m_strLogFileName.Format(
324  "%s%s%s", LOGFILE_PRE, strThreadContext.Get(), LOGFILE_EXT);
325 
327 
328  config.Reset();
329  if (!config.Load()) {
330  return false;
331  };
332 
333  bool bIsNew(false);
334  if (!config.CheckSet_str("logfile", strThreadContext,
335  pLogger->m_strLogFileName,
336  pLogger->m_strLogFileName, bIsNew)) {
337  return false;
338  }
339 
340  if (!config.Save()) {
341  return false;
342  };
343  config.Reset();
344  }
345 
346 #ifdef ANDROID
347  if (OTPaths::HomeFolder().Exists())
348 #endif
349  if (!OTPaths::AppendFile(pLogger->m_strLogFilePath,
351  pLogger->m_strLogFileName)) {
352  return false;
353  };
354 
355  pLogger->m_bInitialized = true;
356 
357  // Set the new log-assert function pointer.
358  Assert* pLogAssert = new Assert(OTLog::logAssert);
359  std::swap(pLogAssert, Assert::s_pAssert);
360  delete pLogAssert;
361  pLogAssert = nullptr;
362 
363  return true;
364  }
365  else {
366  return false;
367  }
368 }
369 
370 // static
372 {
373  return nullptr != pLogger && pLogger->m_bInitialized;
374 }
375 
376 // static
378 {
379  if (nullptr != pLogger) {
380  delete pLogger;
381  pLogger = nullptr;
382  return true;
383  }
384  return false;
385 }
386 
387 // static
388 bool OTLog::CheckLogger(OTLog* pLogger)
389 {
390  if (nullptr != pLogger && pLogger->m_bInitialized) return true;
391 
392  OT_FAIL;
393 }
394 
395 // OTLog Constants.
396 
397 // Compiled into OTLog:
398 
399 const char* OTLog::Version()
400 {
401  return OTLog::GetVersion().Get();
402 }
404 {
405  return m_strVersion;
406 }
407 
408 const char* OTLog::PathSeparator()
409 {
410  return OTLog::GetPathSeparator().Get();
411 }
413 {
414  return m_strPathSeparator;
415 }
416 
417 // Set in constructor:
418 
420 {
421  return pLogger->m_strThreadContext;
422 }
423 
424 const char* OTLog::LogFilePath()
425 {
426  return OTLog::GetLogFilePath().Get();
427 }
429 {
430  return pLogger->m_strLogFilePath;
431 }
432 
433 // static
435 {
436  if (nullptr != pLogger)
437  return pLogger->m_nLogLevel;
438  else
439  return 0;
440 }
441 
442 // static
443 bool OTLog::SetLogLevel(const int32_t& nLogLevel)
444 {
445  if (nullptr == pLogger) {
446  OT_FAIL;
447  }
448  else {
449  pLogger->m_nLogLevel = nLogLevel;
450  return true;
451  }
452 }
453 
454 // OTLog Functions
455 
456 // If there's no logfile, then send it to stderr.
457 // (So we can still see it on the screen, but it doesn't interfere with any
458 // command line utilities who might otherwise interpret it as their own input,
459 // if I was actually writing to stdout.)
460 //
461 // static
462 bool OTLog::LogToFile(const OTString& strOutput)
463 {
464  // We now do this either way.
465  {
466  std::cerr << strOutput;
467  std::cerr.flush();
468  }
469 
470  // now log to file, if we can.
471 
472  bool bHaveLogger(false);
473  if (nullptr != pLogger)
474  if (pLogger->IsInitialized()) bHaveLogger = true;
475 
476  // lets check if we are Initialized in this context
477  if (bHaveLogger) CheckLogger(OTLog::pLogger);
478 
479  bool bSuccess = false;
480 
481  if (bHaveLogger) {
482  // Append to logfile
483  if ((strOutput.Exists()) &&
484  (OTLog::pLogger->m_strLogFilePath.Exists())) {
485  std::ofstream logfile;
486  logfile.open(OTLog::LogFilePath(), std::ios::app);
487 
488  if (!logfile.fail()) {
489  logfile << strOutput;
490  logfile.close();
491  bSuccess = true;
492  }
493  }
494  }
495 
496  return bSuccess;
497 }
498 
500 {
501  // lets check if we are Initialized in this context
502  CheckLogger(OTLog::pLogger);
503 
504  uint32_t uIndex = static_cast<uint32_t>(nIndex);
505 
506  if ((nIndex < 0) || (uIndex >= OTLog::pLogger->logDeque.size())) {
507  otErr << __FUNCTION__ << ": index out of bounds: " << nIndex << "\n";
508  return "";
509  }
510 
511  if (nullptr != OTLog::pLogger->logDeque.at(uIndex))
512  ; // check for null
513  else
514  OT_FAIL;
515 
516  const OTString strLogEntry = *OTLog::pLogger->logDeque.at(uIndex);
517 
518  if (strLogEntry.Exists())
519  return strLogEntry;
520  else
521  return "";
522 }
523 
524 // We keep 1024 logs in memory, to make them available via the API.
525 
527 {
528  // lets check if we are Initialized in this context
529  CheckLogger(OTLog::pLogger);
530 
531  return static_cast<int32_t>(OTLog::pLogger->logDeque.size());
532 }
533 
535 {
536  // lets check if we are Initialized in this context
537  CheckLogger(OTLog::pLogger);
538 
539  if (OTLog::pLogger->logDeque.size() <= 0) return nullptr;
540 
541  if (nullptr != OTLog::pLogger->logDeque.front())
542  ; // check for null
543  else
544  OT_FAIL;
545 
546  const OTString strLogEntry = *OTLog::pLogger->logDeque.front();
547 
548  if (strLogEntry.Exists())
549  return strLogEntry;
550  else
551  return "";
552 }
553 
555 {
556  // lets check if we are Initialized in this context
557  CheckLogger(OTLog::pLogger);
558 
559  if (OTLog::pLogger->logDeque.size() <= 0) return nullptr;
560 
561  if (nullptr != OTLog::pLogger->logDeque.back())
562  ; // check for null
563  else
564  OT_FAIL;
565 
566  const OTString strLogEntry = *OTLog::pLogger->logDeque.back();
567 
568  if (strLogEntry.Exists())
569  return strLogEntry;
570  else
571  return "";
572 }
573 
574 // static
576 {
577  // lets check if we are Initialized in this context
578  CheckLogger(OTLog::pLogger);
579 
580  if (OTLog::pLogger->logDeque.size() <= 0) return false;
581 
582  OTString* strLogFront = OTLog::pLogger->logDeque.front();
583  if (nullptr != strLogFront) delete strLogFront;
584  strLogFront = nullptr;
585 
586  OTLog::pLogger->logDeque.pop_front();
587 
588  return true;
589 }
590 
591 // static
593 {
594  // lets check if we are Initialized in this context
595  CheckLogger(OTLog::pLogger);
596 
597  if (OTLog::pLogger->logDeque.size() <= 0) return false;
598 
599  OTString* strLogBack = OTLog::pLogger->logDeque.back();
600  if (nullptr != strLogBack) delete strLogBack;
601  strLogBack = nullptr;
602 
603  OTLog::pLogger->logDeque.pop_back();
604 
605  return true;
606 }
607 
608 // static
609 bool OTLog::PushMemlogFront(const OTString& strLog)
610 {
611  // lets check if we are Initialized in this context
612  CheckLogger(OTLog::pLogger);
613 
614  OT_ASSERT(strLog.Exists());
615 
616  OTLog::pLogger->logDeque.push_front(new OTString(strLog));
617 
618  if (OTLog::pLogger->logDeque.size() > LOG_DEQUE_SIZE) {
619  OTLog::PopMemlogBack(); // We start removing from the back when it
620  // reaches this size.
621  }
622 
623  return true;
624 }
625 
626 // static
627 bool OTLog::PushMemlogBack(const OTString& strLog)
628 {
629  // lets check if we are Initialized in this context
630  CheckLogger(OTLog::pLogger);
631 
632  OT_ASSERT(strLog.Exists());
633 
634  OTLog::pLogger->logDeque.push_back(new OTString(strLog));
635 
636  return true;
637 }
638 
639 // static
640 bool OTLog::SleepSeconds(int64_t lSeconds)
641 {
642 #ifdef _WIN32
643  Sleep(static_cast<DWORD>(1000 * lSeconds));
644 #else
645  sleep(lSeconds);
646 #endif
647  return true;
648 }
649 
650 // static
651 bool OTLog::SleepMilliseconds(int64_t lMilliseconds)
652 {
653 #ifdef _WIN32
654  Sleep(static_cast<DWORD>(lMilliseconds));
655 #else
656  usleep(lMilliseconds * 1000);
657 #endif
658  return true;
659 }
660 
661 // This function is for things that should NEVER happen.
662 // In fact you should never even call it -- use the OT_ASSERT() macro instead.
663 // This Function is now only for logging, you
664 // static private
665 size_t OTLog::logAssert(const char* szFilename, size_t nLinenumber,
666  const char* szMessage)
667 {
668  if (nullptr != szMessage) {
669 #ifndef ANDROID // if NOT android
670  std::cerr << szMessage << "\n";
671 
672  LogToFile(szMessage);
673  LogToFile("\n");
674 
675 #else // if Android
676  __android_log_write(ANDROID_LOG_FATAL, "OT Assert (or Fail)",
677  szMessage);
678 #endif
679 
680  print_stacktrace();
681  }
682 
683  if ((nullptr != szFilename)) {
684 #ifndef ANDROID // if NOT android
685 
686  // Pass it to LogToFile, as this always logs.
687  //
688  OTString strTemp;
689  strTemp.Format("\nOT_ASSERT in %s at line %d\n", szFilename,
690  nLinenumber);
691  LogToFile(strTemp.Get());
692 
693 #else // if Android
694  OTString strAndroidAssertMsg;
695  strAndroidAssertMsg.Format("\nOT_ASSERT in %s at line %d\n", szFilename,
696  nLinenumber);
697  __android_log_write(ANDROID_LOG_FATAL, "OT Assert",
698  (const char*)strAndroidAssertMsg.Get());
699 #endif
700  }
701 
702  print_stacktrace();
703 
704  return 1; // normal
705 }
706 
707 // For normal output. The higher the verbosity, the less important the message.
708 // (Verbose level 0 ALWAYS logs.) Currently goes to stdout.
709 
710 void OTLog::Output(int32_t nVerbosity, const char* szOutput)
711 {
712  bool bHaveLogger(false);
713  if (nullptr != pLogger)
714  if (pLogger->IsInitialized()) bHaveLogger = true;
715 
716  // lets check if we are Initialized in this context
717  if (bHaveLogger) CheckLogger(OTLog::pLogger);
718 
719  // If log level is 0, and verbosity of this message is 2, don't bother
720  // logging it.
721  // if (nVerbosity > OTLog::__CurrentLogLevel || (nullptr == szOutput))
722  if ((nVerbosity > LogLevel()) || (nullptr == szOutput) ||
723  (LogLevel() == (-1)))
724  return;
725 
726  // We store the last 1024 logs so programmers can access them via the API.
727  if (bHaveLogger) OTLog::PushMemlogFront(szOutput);
728 
729 #ifndef ANDROID // if NOT android
730 
731  LogToFile(szOutput);
732 
733 #else // if IS Android
734  /*
735  typedef enum android_LogPriority {
736  ANDROID_LOG_UNKNOWN = 0,
737  ANDROID_LOG_DEFAULT, // only for SetMinPriority()
738  ANDROID_LOG_VERBOSE,
739  ANDROID_LOG_DEBUG,
740  ANDROID_LOG_INFO,
741  ANDROID_LOG_WARN,
742  ANDROID_LOG_ERROR,
743  ANDROID_LOG_FATAL,
744  ANDROID_LOG_SILENT, // only for SetMinPriority(); must be last
745  } android_LogPriority;
746  */
747  switch (nVerbosity) {
748  case 0:
749  case 1:
750  __android_log_write(ANDROID_LOG_INFO, "OT Output", szOutput);
751  break;
752  case 2:
753  case 3:
754  __android_log_write(ANDROID_LOG_DEBUG, "OT Debug", szOutput);
755  break;
756  case 4:
757  case 5:
758  __android_log_write(ANDROID_LOG_VERBOSE, "OT Verbose", szOutput);
759  break;
760  default:
761  __android_log_write(ANDROID_LOG_UNKNOWN, "OT Unknown", szOutput);
762  break;
763  }
764 #endif
765 }
766 
767 // the vOutput is to avoid name conflicts.
768 void OTLog::vOutput(int32_t nVerbosity, const char* szOutput, ...)
769 {
770  bool bHaveLogger(false);
771  if (nullptr != pLogger)
772  if (pLogger->IsInitialized()) bHaveLogger = true;
773 
774  // lets check if we are Initialized in this context
775  if (bHaveLogger) CheckLogger(OTLog::pLogger);
776 
777  // If log level is 0, and verbosity of this message is 2, don't bother
778  // logging it.
779  if (((0 != LogLevel()) && (nVerbosity > LogLevel())) ||
780  (nullptr == szOutput))
781  return;
782 
783  va_list args;
784  va_start(args, szOutput);
785 
786  std::string strOutput;
787 
788  const bool bFormatted = OTString::vformat(szOutput, &args, strOutput);
789 
790  va_end(args);
791 
792  if (bFormatted)
793  OTLog::Output(nVerbosity, strOutput.c_str());
794  else
795  OT_FAIL;
796  return;
797 }
798 
799 // the vError name is to avoid name conflicts
800 void OTLog::vError(const char* szError, ...)
801 {
802  bool bHaveLogger(false);
803  if (nullptr != pLogger)
804  if (pLogger->IsInitialized()) bHaveLogger = true;
805 
806  // lets check if we are Initialized in this context
807  if (bHaveLogger) CheckLogger(OTLog::pLogger);
808 
809  if ((nullptr == szError)) return;
810 
811  va_list args;
812  va_start(args, szError);
813 
814  std::string strOutput;
815 
816  const bool bFormatted = OTString::vformat(szError, &args, strOutput);
817 
818  va_end(args);
819 
820  if (bFormatted)
821  OTLog::Error(strOutput.c_str());
822  else
823  OT_FAIL;
824 }
825 
826 // An error has occurred, that somehow doesn't match the Assert or Output
827 // functions.
828 // So use this one instead. This ALWAYS logs and currently it all goes to
829 // stderr.
830 
831 void OTLog::Error(const char* szError)
832 {
833  bool bHaveLogger(false);
834  if (nullptr != pLogger)
835  if (pLogger->IsInitialized()) bHaveLogger = true;
836 
837  // lets check if we are Initialized in this context
838  if (bHaveLogger) CheckLogger(OTLog::pLogger);
839 
840  if ((nullptr == szError)) return;
841 
842  // We store the last 1024 logs so programmers can access them via the API.
843  if (bHaveLogger) OTLog::PushMemlogFront(szError);
844 
845 #ifndef ANDROID // if NOT android
846 
847  LogToFile(szError);
848 
849 #else // if Android
850  __android_log_write(ANDROID_LOG_ERROR, "OT Error", szError);
851 #endif
852 }
853 
854 // NOTE: if you have problems compiling on certain platforms, due to the use
855 // of errno, then just use preprocessor directives to carve those portions out
856 // of this function, replacing with a message about the unavailability of errno.
857 //
858 // static
859 void OTLog::Errno(const char* szLocation) // stderr
860 {
861  bool bHaveLogger(false);
862  if (nullptr != pLogger)
863  if (pLogger->IsInitialized()) bHaveLogger = true;
864 
865  // lets check if we are Initialized in this context
866  if (bHaveLogger) CheckLogger(OTLog::pLogger);
867 
868  const int32_t errnum = errno;
869  char buf[128];
870  buf[0] = '\0';
871 
872  int32_t nstrerr = 0;
873  char* szErrString = nullptr;
874 
875 //#if((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) &&
877 
878 #if defined(_GNU_SOURCE) && defined(__linux__) && !defined(ANDROID)
879  szErrString = strerror_r(errnum, buf, 127);
880 #elif(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
881  nstrerr = strerror_r(errnum, buf,
882  127); // (strerror_r is threadsafe version of strerror)
883 #endif
884 
885  const char* szFunc = "OTLog::Errno";
886  const char* sz_location = (nullptr == szLocation) ? "" : szLocation;
887 
888  if (nullptr == szErrString) szErrString = buf;
889 
890  if (0 == nstrerr)
891  otErr << szFunc << " " << sz_location << ": errno " << errnum << ": "
892  << (szErrString[0] != '\0' ? szErrString : "") << ".\n";
893  else
894  otErr << szFunc << " " << sz_location << ": errno: " << errnum
895  << ". (Unable to retrieve error string for that number.)\n";
896 }
897 
898 // String Helpers
899 
900 bool OTLog::StringFill(OTString& out_strString, const char* szString,
901  int32_t iLength, const char* szAppend)
902 {
903  std::string strString(szString);
904 
905  if (nullptr != szAppend) strString.append(szAppend);
906 
907  for (; (static_cast<int32_t>(strString.length()) < iLength);
908  strString.append(" "))
909  ;
910 
911  out_strString.Set(strString.c_str());
912 
913  return true;
914 }
915 
916 // SIGNALS
917 //
918 // To get the most mileage out of this signal handler,
919 // compile it with the options: -g -rdynamic
920 //
921 // Signal Handler
922 //
923 //
924 
925 void ot_terminate(void);
926 
927 namespace
928 {
929 
930 #ifdef _MSC_VER
931 #pragma warning(push)
932 #pragma warning(disable : 4800) // warning C4800: forcing constant value.
933 #endif
934 
935 // invoke set_terminate as part of global constant initialization
936 static const bool SET_TERMINATE = std::set_terminate(ot_terminate);
937 
938 #ifdef _MSC_VER
939 #pragma warning(pop)
940 #endif
941 }
942 
943 // This is our custom std::terminate(). Also called for uncaught exceptions.
945 {
946  if (auto e = std::current_exception()) {
947  try {
948  std::rethrow_exception(e);
949  }
950  catch (const std::exception& e) {
951  std::cerr << "ot_terminate: " << __FUNCTION__
952  << " caught unhandled exception."
953  << " type: " << typeid(e).name()
954  << " what(): " << e.what() << std::endl;
955  }
956  catch (...) {
957  std::cerr << "ot_terminate: " << __FUNCTION__
958  << " caught unknown/unhandled exception." << std::endl;
959  }
960  }
961 
962  print_stacktrace();
963 
964  // Call the default std::terminate() handler.
965  std::abort();
966 }
967 
968 #ifdef _WIN32 // Windows SIGNALS
969 
970 // The windows version is from Stefan Wörthmüller, who wrote an excellent
971 // article
972 // at Dr. Dobbs Journal here:
973 // http://www.drdobbs.com/architecture-and-design/185300443
974 //
975 
976 // static
978 {
979  static int32_t nCount = 0;
980 
981  if (0 == nCount) {
982  ++nCount;
983  SetUnhandledExceptionFilter(
984  (LPTOP_LEVEL_EXCEPTION_FILTER)Win32FaultHandler);
985  }
986 }
987 
988 #else // if _WIN32, else: UNIX -- SIGNALS
989 
990 // CREDIT: the Linux / GNU portion of the signal handler comes from
991 // StackOverflow,
992 // where several answers are combined here.
993 // http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes
994 //
995 
997 {
998  struct ucontext* uc_link;
999  stack_t uc_stack;
1000  struct sigcontext uc_mcontext;
1001  sigset_t uc_sigmask;
1002 };
1003 
1004 extern "C" {
1005 // This structure mirrors the one found in /usr/include/asm/ucontext.h
1006 //
1007 
1008 void crit_err_hdlr(int32_t sig_num, siginfo_t* info, void* ucontext);
1009 }
1010 
1011 #if defined(OT_NO_DEMANGLING_STACK_TRACE)
1012 
1013 // this version doesn't do demangling.
1014 void crit_err_hdlr(int32_t sig_num, siginfo_t* info, void* ucontext)
1015 {
1016  void* array[50];
1017  void* caller_address;
1018  char** messages;
1019  int32_t size, i;
1020  sig_ucontext_t* uc;
1021 
1022  static std::mutex the_Mutex;
1023 
1024  std::lock_guard<std::mutex> lock(the_Mutex);
1025 
1026  uc = static_cast<sig_ucontext_t*>(ucontext);
1027 
1028  // Get the address at the time the signal was raised from the EIP (x86)
1029  caller_address = (void*)uc->uc_mcontext.eip;
1030 
1031  fprintf(stderr, "signal %d (%s), address is %p from %p\n", sig_num,
1032  strsignal(sig_num), info->si_addr, (void*)caller_address);
1033 
1034  size = backtrace(array, 50);
1035 
1036  // overwrite sigaction with caller's address
1037  //
1038  array[1] = caller_address;
1039 
1040  messages = backtrace_symbols(array, size);
1041 
1042  // skip first stack frame (points here)
1043  //
1044  for (i = 1; i < size && messages != nullptr; ++i) {
1045  fprintf(stderr, "[bt]: (%d) %s\n", i, messages[i]);
1046  }
1047 
1048  free(messages);
1049 
1050  _exit(0);
1051 }
1052 
1053 #else // #if no demangling, #else...
1054 
1055 // This version DOES do demangling.
1056 //
1057 /*
1058 void crit_err_hdlr(int32_t sig_num, siginfo_t* info, void* ucontext)
1059 {
1060  sig_ucontext_t * uc = (sig_ucontext_t *)ucontext;
1061 
1062  void * caller_address = (void *) uc->uc_mcontext.eip; // x86 specific
1063 
1064  std::cerr << "signal " << sig_num
1065  << " (" << strsignal(sig_num) << "), address is "
1066  << info->si_addr << " from " << caller_address
1067  << std::endl << std::endl;
1068 
1069  void * array[50];
1070  int32_t size = backtrace(array, 50);
1071 
1072  array[1] = caller_address;
1073 
1074  char ** messages = backtrace_symbols(array, size);
1075 
1076  // skip first stack frame (points here)
1077  for (int32_t i = 1; i < size && messages != nullptr; ++i)
1078  {
1079  char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
1080 
1081  // find parantheses and +address offset surrounding mangled name
1082  for (char *p = messages[i]; *p; ++p)
1083  {
1084  if (*p == '(')
1085  {
1086  mangled_name = p;
1087  }
1088  else if (*p == '+')
1089  {
1090  offset_begin = p;
1091  }
1092  else if (*p == ')')
1093  {
1094  offset_end = p;
1095  break;
1096  }
1097  }
1098 
1099  // if the line could be processed, attempt to demangle the symbol
1100  if (mangled_name && offset_begin && offset_end &&
1101  mangled_name < offset_begin)
1102  {
1103  *mangled_name++ = '\0';
1104  *offset_begin++ = '\0';
1105  *offset_end++ = '\0';
1106 
1107  int32_t status;
1108  char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
1109 
1110  // if demangling is successful, output the demangled function name
1111  if (status == 0)
1112  {
1113  std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
1114  << real_name << "+" << offset_begin << offset_end
1115  << std::endl;
1116 
1117  }
1118  // otherwise, output the mangled function name
1119  else
1120  {
1121  std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
1122  << mangled_name << "+" << offset_begin << offset_end
1123  << std::endl;
1124  }
1125  free(real_name);
1126  }
1127  // otherwise, print the whole line
1128  else
1129  {
1130  std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
1131  }
1132  }
1133  std::cerr << std::endl;
1134 
1135  free(messages);
1136 
1137  _exit(0);
1138 }
1139 */
1140 
1141 void crit_err_hdlr(int32_t sig_num, siginfo_t* info, void* v)
1142 {
1143 #ifndef ANDROID
1144  static std::mutex the_Mutex;
1145 
1146  std::lock_guard<std::mutex> lock(the_Mutex);
1147 
1148  OT_ASSERT(nullptr != v);
1149 
1150 #ifdef _LP64
1151  typedef uint64_t ot_ulong;
1152 #else
1153  typedef uint32_t ot_ulong;
1154 #endif // lp64
1155 
1156  ot_ulong eip = 0;
1157  ucontext_t* uc = (ucontext_t*)v;
1158 
1159 #if defined(__APPLE__)
1160 #ifdef __arm__
1161  _STRUCT_MCONTEXT* mc; // mcontext_t seems to be missing from arm/_structs.h
1162  // cppcheck-suppress unreadVariable
1163  mc = uc->uc_mcontext;
1164 // eip = mc->__ss.__eip; // arm doesn't have eip
1165 #else
1166  mcontext_t mc;
1167  mc = uc->uc_mcontext;
1168 #ifdef _LP64
1169  eip = mc->__ss.__rip;
1170 #else
1171  eip = mc->__ss.__eip;
1172 #endif
1173 #endif // __arm__
1174 #elif defined(__linux__)
1175  mcontext_t* mc;
1176  struct sigcontext* ctx;
1177  mc = &uc->uc_mcontext;
1178  ctx = (struct sigcontext*)mc;
1179 #ifdef __i386__
1180  eip = ctx->eip;
1181 #else
1182  eip = ctx->rip;
1183 #endif
1184 #elif defined(__FreeBSD__)
1185  mcontext_t* mc;
1186  mc = &uc->uc_mcontext;
1187 #ifdef __i386__
1188  eip = mc->mc_eip;
1189 #elif defined(__amd64__)
1190  eip = mc->mc_rip;
1191 #endif
1192  ot_ulong addr = (ot_ulong)info->si_addr;
1193  if (__FreeBSD__ < 7) {
1194  /*
1195  * FreeBSD /usr/src/sys/i386/i386/trap.c kludgily reuses
1196  * frame->tf_err as somewhere to put the faulting address
1197  * (cr2) when calling into the generic signal dispatcher.
1198  * Unfortunately, that means that the bit in tf_err that says
1199  * whether this is a read or write fault is irretrievably gone.
1200  * So we have to figure it out. Let's assume that if the page
1201  * is already mapped in core, it is a write fault. If not, it is a
1202  * read fault.
1203  *
1204  * This is apparently fixed in FreeBSD 7, but I don't have any
1205  * FreeBSD 7 machines on which to verify this.
1206  */
1207  char vec;
1208  int32_t r;
1209 
1210  vec = 0;
1211  r = mincore((void*)addr, 1, &vec);
1212  // iprint("FreeBSD fault [%d]: addr=%p[%p] mincore=%d vec=%#x
1213  // errno=%d\n", signo, addr, (uchar*)addr-uzero, r, vec, errno);
1214  if (r < 0 || vec == 0)
1215  mc->mc_err = 0; /* read fault */
1216  else
1217  mc->mc_err = 2; /* write fault */
1218  }
1219 #else
1220 #error "Unknown OS in sigsegv"
1221 #endif
1222 
1223  void* caller_address = (void*)eip;
1224 
1225  std::cerr << "signal " << sig_num << " (" << strsignal(sig_num)
1226  << "), address is " << info->si_addr << " from " << caller_address
1227  << std::endl << std::endl;
1228 
1229  void* array[50];
1230  int32_t size = backtrace(array, 50);
1231 
1232  array[1] = caller_address;
1233 
1234  char** messages = backtrace_symbols(array, size);
1235 
1236  // skip first stack frame (points here)
1237  for (int32_t i = 1; i < size && messages != nullptr; ++i) {
1238  char* mangled_name = 0, *offset_begin = 0, *offset_end = 0;
1239 
1240  // find parantheses and +address offset surrounding mangled name
1241  for (char* p = messages[i]; *p; ++p) {
1242  if (*p == '(') {
1243  mangled_name = p;
1244  }
1245  else if (*p == '+') {
1246  offset_begin = p;
1247  }
1248  else if (*p == ')') {
1249  offset_end = p;
1250  break;
1251  }
1252  }
1253 
1254  // if the line could be processed, attempt to demangle the symbol
1255  if (mangled_name && offset_begin && offset_end &&
1256  mangled_name < offset_begin) {
1257  *mangled_name++ = '\0';
1258  *offset_begin++ = '\0';
1259  *offset_end++ = '\0';
1260 
1261  int32_t status;
1262  char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
1263 
1264  // if demangling is successful, output the demangled function name
1265  if (status == 0) {
1266  std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
1267  << real_name << "+" << offset_begin << offset_end
1268  << std::endl;
1269 
1270  }
1271  // otherwise, output the mangled function name
1272  else {
1273  std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
1274  << mangled_name << "+" << offset_begin << offset_end
1275  << std::endl;
1276  }
1277  free(real_name);
1278  }
1279  // otherwise, print the whole line
1280  else {
1281  std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
1282  }
1283  }
1284  std::cerr << std::endl;
1285 
1286  free(messages);
1287 #endif // #ifndef ANDROID
1288  _exit(0);
1289 }
1290 
1291 #endif // defined(OT_NO_DEMANGLING_STACK_TRACE)
1292 
1293 #ifndef OT_HANDLE_SIGNAL
1294 #define OT_HANDLE_SIGNAL(OT_SIGNAL_TYPE) \
1295  { \
1296  struct sigaction new_action, old_action; \
1297  new_action.sa_sigaction = crit_err_hdlr; \
1298  sigemptyset(&new_action.sa_mask); \
1299  new_action.sa_flags = SA_RESTART | SA_SIGINFO; \
1300  \
1301  sigaction(OT_SIGNAL_TYPE, nullptr, &old_action); \
1302  \
1303  if (old_action.sa_handler != SIG_IGN) { \
1304  if (sigaction(OT_SIGNAL_TYPE, &new_action, nullptr) != 0) { \
1305  otErr << "OTLog::SetupSignalHandler: Failed setting signal " \
1306  "handler for error " << OT_SIGNAL_TYPE << " (" \
1307  << strsignal(OT_SIGNAL_TYPE) << ")\n"; \
1308  abort(); \
1309  } \
1310  } \
1311  }
1312 #endif
1313 
1314 // static
1316 {
1317  static int32_t nCount = 0;
1318 
1319  if (0 == nCount) {
1320  ++nCount;
1321 
1322  OT_HANDLE_SIGNAL(SIGINT) // Ctrl-C. (So we can shutdown gracefully, I
1323  // suppose, on Ctrl-C.)
1324  OT_HANDLE_SIGNAL(SIGSEGV) // Segmentation fault.
1325  // OT_HANDLE_SIGNAL(SIGABRT) // Abort.
1326  OT_HANDLE_SIGNAL(SIGBUS) // Bus error
1327  // OT_HANDLE_SIGNAL(SIGHUP) // I believe this is for sending a
1328  // "restart" signal to your process, that sort of thing.
1329  OT_HANDLE_SIGNAL(SIGTERM) // Used by kill pid (NOT kill -9 pid). Used
1330  // for "killing softly."
1331  OT_HANDLE_SIGNAL(SIGILL) // Illegal instruction.
1332  OT_HANDLE_SIGNAL(SIGTTIN) // SIGTTIN may be sent to a background process
1333  // that attempts to read from its controlling
1334  // terminal.
1335  OT_HANDLE_SIGNAL(SIGTTOU) // SIGTTOU may be sent to a background process
1336  // that attempts to write to its controlling
1337  // terminal.
1338  // OT_HANDLE_SIGNAL(SIGPIPE) // Unix supports the principle of
1339  // piping. When a pipe is broken, the process writing to it is sent the
1340  // SIGPIPE.
1341  // OT_HANDLE_SIGNAL(SIGKILL) // kill -9. "The receiving process
1342  // cannot perform any clean-up upon receiving this signal."
1343  OT_HANDLE_SIGNAL(SIGFPE) // Floating point exception.
1344  OT_HANDLE_SIGNAL(SIGXFSZ) // SIGXFSZ is the signal sent to a process
1345  // when it grows a file larger than the
1346  // maximum allowed size.
1347  // OT_HANDLE_SIGNAL(SIGQUIT) // SIGQUIT is the signal sent to a
1348  // process by its controlling terminal when the user requests that the
1349  // process perform a core dump.
1350  OT_HANDLE_SIGNAL(SIGSYS) // sent when a process supplies an incorrect
1351  // argument to a system call.
1352  // OT_HANDLE_SIGNAL(SIGTRAP) // used by debuggers
1353  }
1354 }
1355 
1356 #endif // #if windows, #else (unix) #endif. (SIGNAL handling.)
1357 
1358 } // namespace opentxs
1359 
1360 #ifdef _WIN32 // Windows SIGNALS
1361 
1362 LONG Win32FaultHandler(struct _EXCEPTION_POINTERS* ExInfo)
1363 {
1364  char* FaultTx = "";
1365 
1366  switch (ExInfo->ExceptionRecord->ExceptionCode) {
1367  case EXCEPTION_ACCESS_VIOLATION:
1368  FaultTx = "ACCESS VIOLATION";
1369  break;
1370  case EXCEPTION_DATATYPE_MISALIGNMENT:
1371  FaultTx = "DATATYPE MISALIGNMENT";
1372  break;
1373  case EXCEPTION_BREAKPOINT:
1374  FaultTx = "BREAKPOINT";
1375  break;
1376  case EXCEPTION_SINGLE_STEP:
1377  FaultTx = "SINGLE STEP";
1378  break;
1379  case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1380  FaultTx = "ARRAY BOUNDS EXCEEDED";
1381  break;
1382  case EXCEPTION_FLT_DENORMAL_OPERAND:
1383  FaultTx = "FLT DENORMAL OPERAND";
1384  break;
1385  case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1386  FaultTx = "FLT DIVIDE BY ZERO";
1387  break;
1388  case EXCEPTION_FLT_INEXACT_RESULT:
1389  FaultTx = "FLT INEXACT RESULT";
1390  break;
1391  case EXCEPTION_FLT_INVALID_OPERATION:
1392  FaultTx = "FLT INVALID OPERATION";
1393  break;
1394  case EXCEPTION_FLT_OVERFLOW:
1395  FaultTx = "FLT OVERFLOW";
1396  break;
1397  case EXCEPTION_FLT_STACK_CHECK:
1398  FaultTx = "FLT STACK CHECK";
1399  break;
1400  case EXCEPTION_FLT_UNDERFLOW:
1401  FaultTx = "FLT UNDERFLOW";
1402  break;
1403  case EXCEPTION_INT_DIVIDE_BY_ZERO:
1404  FaultTx = "INT DIVIDE BY ZERO";
1405  break;
1406  case EXCEPTION_INT_OVERFLOW:
1407  FaultTx = "INT OVERFLOW";
1408  break;
1409  case EXCEPTION_PRIV_INSTRUCTION:
1410  FaultTx = "PRIV INSTRUCTION";
1411  break;
1412  case EXCEPTION_IN_PAGE_ERROR:
1413  FaultTx = "IN PAGE ERROR";
1414  break;
1415  case EXCEPTION_ILLEGAL_INSTRUCTION:
1416  FaultTx = "ILLEGAL INSTRUCTION";
1417  break;
1418  case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1419  FaultTx = "NONCONTINUABLE EXCEPTION";
1420  break;
1421  case EXCEPTION_STACK_OVERFLOW:
1422  FaultTx = "STACK OVERFLOW";
1423  break;
1424  case EXCEPTION_INVALID_DISPOSITION:
1425  FaultTx = "INVALID DISPOSITION";
1426  break;
1427  case EXCEPTION_GUARD_PAGE:
1428  FaultTx = "GUARD PAGE";
1429  break;
1430  default:
1431  FaultTx = "(unknown)";
1432  break;
1433  }
1434  int32_t wsFault = ExInfo->ExceptionRecord->ExceptionCode;
1435  void* CodeAdress = ExInfo->ExceptionRecord->ExceptionAddress;
1436 
1437  // (using stderr.)
1438  // sgLogFile = fopen("Win32Fault.log", "w");
1439 
1440  if (stderr != nullptr) {
1441  fprintf(stderr,
1442  "****************************************************\n");
1443  fprintf(stderr, "*** A Programm Fault occured:\n");
1444  fprintf(stderr, "*** Error code %08X: %s\n", wsFault, FaultTx);
1445  fprintf(stderr,
1446  "****************************************************\n");
1447  fprintf(stderr, "*** Address: %08X\n", (int32_t)CodeAdress);
1448  fprintf(stderr, "*** Flags: %08X\n",
1449  ExInfo->ExceptionRecord->ExceptionFlags);
1450 
1451 #if defined(_CONSOLE)
1452  printf("\n");
1453  printf("*** A Programm Fault occured:\n");
1454  printf("*** Error code %08X: %s\n", wsFault, FaultTx);
1455 #endif
1456 /* This infomation ssems to be wrong
1457 if(ExInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
1458 {
1459 fprintf(stderr, "****************************************************\n");
1460 fprintf(stderr, "*** Attempted to %s to address %08LX \n",
1461 ExInfo->ExceptionRecord->ExceptionInformation[0] ? "write" : "read",
1462 ExInfo->ExceptionRecord->ExceptionInformation[1]);
1463 
1464 }
1465 */
1466 #ifdef _WIN64
1467 // LogStackFrames(CodeAdress, (char *)ExInfo->ContextRecord->Rbp);
1468 #else
1469  LogStackFrames(CodeAdress, (char*)ExInfo->ContextRecord->Ebp);
1470 #endif
1471 
1472  // fclose(sgLogFile);
1473  }
1474 
1475  /*if(want to continue)
1476  {
1477  ExInfo->ContextRecord->Eip++;
1478  #if defined (_CONSOLE)
1479  printf("*** Trying to continue\n");
1480  printf("\n");
1481  #endif
1482  return EXCEPTION_CONTINUE_EXECUTION;
1483  }
1484  */
1485 
1486  printf("*** Terminating\n");
1487  printf("\n");
1488  return EXCEPTION_EXECUTE_HANDLER;
1489 }
1491 // Unwind the stack and save its return addresses to the logfile
1493 
1494 void LogStackFrames(void* FaultAdress, char* eNextBP)
1495 
1496 {
1497 #if defined(_WIN64)
1498 
1499  typedef USHORT(WINAPI * CaptureStackBackTraceType)(
1500  __in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
1501 
1502  HMODULE lLoadedLib = LoadLibrary(L"kernel32.dll");
1503  if (nullptr == lLoadedLib) OT_FAIL;
1504  CaptureStackBackTraceType func = (CaptureStackBackTraceType)(
1505  GetProcAddress(lLoadedLib, "RtlCaptureStackBackTrace"));
1506 
1507  if (func == nullptr) return;
1508 
1509  // Quote from Microsoft Documentation:
1510  // ## Windows Server 2003 and Windows XP:
1511  // ## The sum of the FramesToSkip and FramesToCapture parameters must be
1512  // less than 63.
1513  const int32_t kMaxCallers = 62;
1514 
1515  void* callers[kMaxCallers];
1516  int32_t count = (func)(0, kMaxCallers, callers, nullptr);
1517  for (int32_t i = 0; i < count; i++)
1518  fprintf(stderr, "*** %d called from %p\n", i, callers[i]);
1519 
1520 #elif defined(_WIN32) // not _WIN64 ? Must be _WIN32
1521 
1522  char* pBP = nullptr;
1523  uint32_t i = 0, x = 0, BpPassed = 0;
1524  static int32_t CurrentlyInTheStackDump = 0;
1525 
1526  if (CurrentlyInTheStackDump) {
1527  fprintf(stderr, "\n***\n*** Recursive Stack Dump skipped\n***\n");
1528  return;
1529  }
1530 
1531  fprintf(stderr, "****************************************************\n");
1532  fprintf(stderr, "*** CallStack:\n");
1533  fprintf(stderr, "****************************************************\n");
1534 
1535  /* ====================================================================== */
1536  /* */
1537  /* BP +x ... -> == SP (current top of stack) */
1538  /* ... -> Local data of current function */
1539  /* BP +4 0xabcd -> 32 address of calling function */
1540  /* +<==BP 0xabcd -> Stack address of next stack frame (0, if end) */
1541  /* | BP -1 ... -> Aruments of function call */
1542  /* Y */
1543  /* | BP -x ... -> Local data of calling function */
1544  /* | */
1545  /* Y (BP)+4 0xabcd -> 32 address of calling function */
1546  /* +==>BP) 0xabcd -> Stack address of next stack frame (0, if end) */
1547  /* ... */
1548  /* ====================================================================== */
1549  CurrentlyInTheStackDump = 1;
1550 
1551  BpPassed = (eNextBP != nullptr);
1552 
1553  if (!eNextBP) {
1554  _asm mov eNextBP, eBp
1555  }
1556  else
1557  fprintf(stderr, "\n Fault Occured At $ADDRESS:%08LX\n",
1558  (int32_t)FaultAdress);
1559 
1560  // prevent infinite loops
1561  for (i = 0; eNextBP && i < 100; i++) {
1562  pBP = eNextBP; // keep current BasePointer
1563  eNextBP = *(char**)pBP; // dereference next BP
1564 
1565  char* p = pBP + 8;
1566 
1567  // Write 20 Bytes of potential arguments
1568  fprintf(stderr, " with ");
1569  for (x = 0; p < eNextBP && x < 20; p++, x++)
1570  fprintf(stderr, "%02X ", *(uint8_t*)p);
1571 
1572  fprintf(stderr, "\n\n");
1573 
1574  if (i == 1 && !BpPassed)
1575  fprintf(stderr,
1576  "****************************************************\n"
1577  " Fault Occured Here:\n");
1578 
1579  // Write the backjump address
1580  fprintf(stderr, "*** %2d called from $ADDRESS:%08X\n", i,
1581  *(char**)(pBP + 4));
1582 
1583  if (*(char**)(pBP + 4) == nullptr) break;
1584  }
1585 
1586  fprintf(stderr,
1587  "************************************************************\n");
1588  fprintf(stderr, "\n\n");
1589 
1590  CurrentlyInTheStackDump = 0;
1591 
1592  fflush(stderr);
1593 #endif // _WIN64 else (_WIN32) endif
1594 }
1595 
1596 #endif
static EXPORT void vError(const char *szError,...)
Definition: OTLog.cpp:800
OTLOG_IMPORT OTLogStream otLog4
#define LOGFILE_PRE
Definition: OTLog.cpp:241
virtual int overflow(int c)
Definition: OTLog.cpp:278
struct sigcontext uc_mcontext
Definition: OTLog.cpp:1000
static EXPORT void Output(int32_t nVerbosity, const char *szOutput)
Definition: OTLog.cpp:710
static EXPORT const OTString & GetVersion()
Definition: OTLog.cpp:403
#define LOGFILE_EXT
Definition: OTLog.cpp:242
static EXPORT const OTString & GetThreadContext()
Definition: OTLog.cpp:419
static EXPORT bool PopMemlogBack()
Definition: OTLog.cpp:592
static EXPORT bool LogToFile(const OTString &strOutput)
Definition: OTLog.cpp:462
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
static EXPORT bool SetLogLevel(const int32_t &nLogLevel)
Definition: OTLog.cpp:443
static EXPORT OTString GetMemlogAtIndex(int32_t nIndex)
Definition: OTLog.cpp:499
OTLOG_IMPORT OTLogStream otOut
OTLOG_IMPORT OTLogStream otLog3
#define OT_HANDLE_SIGNAL(OT_SIGNAL_TYPE)
Definition: OTLog.cpp:1294
static EXPORT int32_t GetMemlogSize()
Definition: OTLog.cpp:526
#define GLOBAL_LOGFILE
Definition: OTLog.cpp:244
EXPORT bool Exists() const
Definition: OTString.cpp:1035
static EXPORT void Error(const char *szError)
Definition: OTLog.cpp:831
static EXPORT bool PopMemlogFront()
Definition: OTLog.cpp:575
static Assert * s_pAssert
Definition: Assert.hpp:173
static EXPORT const OTString & AppDataFolder()
Definition: OTPaths.cpp:254
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
static EXPORT bool Init(const OTString &strThreadContext="", const int32_t &nLogLevel=0)
Definition: OTLog.cpp:300
static EXPORT const char * Version()
Definition: OTLog.cpp:399
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
static EXPORT void SetupSignalHandler()
Definition: OTLog.cpp:1315
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
#define GLOBAL_LOGNAME
Definition: OTLog.cpp:243
OTLogStream(int _logLevel)
Definition: OTLog.cpp:264
static EXPORT const char * LogFilePath()
Definition: OTLog.cpp:424
#define OTLOG_IMPORT
Definition: OTLog.hpp:169
static EXPORT OTString PeekMemlogBack()
Definition: OTLog.cpp:554
static EXPORT bool Cleanup()
Definition: OTLog.cpp:377
#define OPENTXS_VERSION_STRING
Definition: Version.hpp:14
#define OT_ASSERT(x)
Definition: Assert.hpp:150
static EXPORT bool IsInitialized()
Definition: OTLog.cpp:371
static EXPORT bool PushMemlogBack(const OTString &strLog)
Definition: OTLog.cpp:627
struct ucontext * uc_link
Definition: OTLog.cpp:998
OTLOG_IMPORT OTLogStream otInfo
static EXPORT bool SleepMilliseconds(int64_t lMilliseconds)
Definition: OTLog.cpp:651
#define LOG_DEQUE_SIZE
Definition: OTLog.cpp:165
EXPORT bool Reset()
Definition: OTSettings.cpp:297
static EXPORT bool SleepSeconds(int64_t lSeconds)
Definition: OTLog.cpp:640
#define OT_FAIL
Definition: Assert.hpp:139
static EXPORT int32_t LogLevel()
Definition: OTLog.cpp:434
EXPORT bool CheckSet_str(const OTString &strSection, const OTString &strKey, const OTString &strDefault, OTString &out_strResult, bool &out_bIsNew, const OTString &strComment="")
Definition: OTSettings.cpp:664
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
OTLOG_IMPORT OTLogStream otErr
uint16_t USHORT
Definition: stdafx.hpp:22
static EXPORT const OTString & GetPathSeparator()
Definition: OTLog.cpp:412
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
static EXPORT const OTString & GetLogFilePath()
Definition: OTLog.cpp:428
static EXPORT void Errno(const char *szLocation=nullptr)
Definition: OTLog.cpp:859
static EXPORT bool StringFill(OTString &out_strString, const char *szString, int32_t iLength, const char *szAppend=nullptr)
Definition: OTLog.cpp:900
void crit_err_hdlr(int32_t sig_num, siginfo_t *info, void *ucontext)
Definition: OTLog.cpp:1141
void ot_terminate(void)
Definition: OTLog.cpp:944
static EXPORT bool AppendFile(OTString &out_strPath, const OTString &strBasePath, const OTString &strFileName)
Definition: OTPaths.cpp:1245
static bool vformat(const char *fmt, std::va_list *pvl, std::string &s)
Definition: OTString.cpp:191
static EXPORT void vOutput(int32_t nVerbosity, const char *szOutput,...)
Definition: OTLog.cpp:768
static EXPORT const OTString & HomeFolder()
Definition: OTPaths.cpp:240
static EXPORT const OTString & GlobalConfigFile()
Definition: OTPaths.cpp:286
static EXPORT bool PushMemlogFront(const OTString &strLog)
Definition: OTLog.cpp:609
static EXPORT OTString PeekMemlogFront()
Definition: OTLog.cpp:534
OTLOG_IMPORT OTLogStream otLog5