Line data Source code
1 : #include "logging.hpp"
2 :
3 : #include "distributed.h"
4 : #include "dynamicConfig.hpp"
5 :
6 : #ifdef __ANDROID__
7 : std::string backtrace([[maybe_unused]] int skip) {
8 : ////@todo backtrace for android
9 : return "";
10 : }
11 :
12 : #elif __linux__
13 : #include <cxxabi.h> // for __cxa_demangle
14 : #include <dlfcn.h> // for dladdr
15 : #include <execinfo.h>
16 : #include <signal.h>
17 : #include <stdio.h>
18 : #include <stdlib.h>
19 : #include <unistd.h>
20 :
21 0 : std::string backtrace([[maybe_unused]] int skip) {
22 : void * callstack[128];
23 : const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
24 : char buf[1024];
25 0 : int nFrames = backtrace(callstack, nMaxFrames);
26 0 : char ** symbols = backtrace_symbols(callstack, nFrames);
27 :
28 0 : std::ostringstream trace_buf;
29 0 : for (int i = skip; i < nFrames; i++) {
30 : Dl_info info;
31 0 : if (dladdr(callstack[i], &info)) {
32 : char *demangled = nullptr;
33 : int status;
34 0 : demangled = abi::__cxa_demangle(info.dli_sname, nullptr, 0, &status);
35 0 : std::snprintf(buf, sizeof(buf), "%-3d %*p %s + %zd\n", i, static_cast<int>(2 + sizeof(void *) * 2), callstack[i],
36 0 : status == 0 ? demangled : info.dli_sname, (char *)callstack[i] - (char *)info.dli_saddr);
37 0 : free(demangled);
38 : }
39 : else {
40 0 : std::snprintf(buf, sizeof(buf), "%-3d %*p\n", i, static_cast<int>(2 + sizeof(void *) * 2), callstack[i]);
41 : }
42 0 : trace_buf << buf;
43 0 : std::snprintf(buf, sizeof(buf), "%s\n", symbols[i]);
44 0 : trace_buf << buf;
45 : }
46 0 : free(symbols);
47 0 : if (nFrames == nMaxFrames) trace_buf << "[truncated]\n";
48 0 : return trace_buf.str();
49 0 : }
50 :
51 : #elif defined __MINGW32__
52 : std::string backtrace([[maybe_unused]] int skip) {
53 : ////@todo backtrace for mingw
54 : return "";
55 : }
56 :
57 : #elif defined _WIN32
58 : //#include "dbg_win.h"
59 :
60 : std::string backtrace([[maybe_unused]] int skip) {
61 : /*
62 : std::stringstream buff;
63 : std::vector<windbg::StackFrame> stack = windbg::stack_trace();
64 : buff << "Callstack: \n";
65 : for (unsigned int i = 0; i < stack.size(); ++i) {
66 : buff << "0x" << std::hex << stack[i].address << ": " << stack[i].name << "(" << std::dec << stack[i].line << ") in " << stack[i].module << "\n";
67 : }
68 : return buff.str();
69 : */
70 : return "";
71 : }
72 :
73 : #elif defined __CYGWIN__
74 : std::string backtrace([[maybe_unused]] int skip) {
75 : ///@todo backtrace for cygwin
76 : return "";
77 : }
78 :
79 : #endif
80 :
81 : namespace Logging {
82 :
83 : std::mutex LogIt::_mutex;
84 : std::unique_ptr<std::ofstream> LogIt::_of;
85 :
86 : COMType ct = CT_uci;
87 :
88 : #if defined(__MINGW32__) || defined(__MINGW64__)
89 : # define localtime_r(T,Tm) (localtime_s(Tm,T) ? NULL : Tm)
90 : #endif
91 :
92 43292 : [[nodiscard]] std::string showDate() {
93 43292 : std::stringstream str;
94 : #ifdef _MSC_VER
95 : const auto n = std::chrono::system_clock::now();
96 : str << n;
97 : #else // previous code is only valid on very recent g++ and clang++ currently
98 43292 : const auto msecEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now().time_since_epoch());
99 : char buffer[64];
100 43292 : const auto tt = Clock::to_time_t(Clock::time_point(msecEpoch));
101 : struct tm localTime;
102 43292 : std::strftime(buffer, 63, "%Y-%m-%d %H:%M:%S", localtime_r(&tt, &localTime));
103 43292 : str << buffer << "-" << std::setw(3) << std::setfill('0') << msecEpoch.count() % 1000;
104 : #endif
105 43292 : return str.str();
106 43292 : }
107 :
108 43942 : LogIt::~LogIt() {
109 : std::lock_guard lock(_mutex);
110 43942 : if (_level != logGUI) { // those are "comments" and are prefixed with _protocolComment[ct] ("info string" for UCI)
111 43292 : const std::string rankStr = Distributed::moreThanOneProcess() ? (std::string("(") + std::to_string(Distributed::rank) + ") ") : "";
112 129876 : const std::string str = std::string(_protocolComment[ct]) + std::string(_levelNames[_level]) + showDate() + ": " + rankStr + _buffer.str();
113 43292 : if ( _level >= DynamicConfig::minOutputLevel ) {
114 : #ifdef WITH_FMTLIB
115 : if ( ct == CT_pretty ){
116 : std::cout << fmt::format(_levelStyles[_level], str) << std::endl;
117 : }
118 : else
119 : #endif
120 : std::cout << str << std::endl;
121 : }
122 : // debug file output is *not* depending on DynamicConfig::minOutputLevel
123 43292 : if (_of) (*_of) << str << std::endl;
124 : }
125 : else { // those are direct GUI outputs (like bestmove, feature, option, ...)
126 650 : if ( _level >= DynamicConfig::minOutputLevel ) {
127 560 : std::cout << _buffer.str() << std::flush << std::endl;
128 : }
129 : // debug file output is *not* depending on DynamicConfig::minOutputLevel
130 650 : if (_of) (*_of) << _buffer.str() << std::flush << std::endl;
131 : }
132 : if (_level >= logError) {
133 : #ifdef DEBUG_BACKTRACE
134 : std::cout << backtrace() << std::endl;
135 : #endif
136 : }
137 43942 : if (_level >= logFatal) {
138 : Distributed::finalize();
139 0 : exit(1);
140 : }
141 43942 : }
142 :
143 22 : void hellooo() {
144 : if (Distributed::isMainProcess()) {
145 : #ifdef WITH_NNUE
146 22 : std::cout << Logging::_protocolComment[Logging::ct] << "This is Minic version " << MinicVersion << " (NNUE available)" << std::endl;
147 : #else
148 : std::cout << Logging::_protocolComment[Logging::ct] << "This is Minic version " << MinicVersion << std::endl;
149 : #endif
150 : if (Distributed::moreThanOneProcess()) {
151 : std::cout << Logging::_protocolComment[Logging::ct] << "MPI version running on " << Distributed::worldSize << " process" << std::endl;
152 : }
153 : }
154 22 : }
155 :
156 22 : void init() {
157 22 : if (DynamicConfig::debugMode) {
158 0 : if (DynamicConfig::debugFile.empty()) DynamicConfig::debugFile = "minic.debug";
159 : LogIt::_of = std::unique_ptr<std::ofstream>(
160 0 : new std::ofstream(DynamicConfig::debugFile + "_" + std::to_string(Distributed::rank) + "_" +
161 0 : std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now().time_since_epoch()).count())));
162 : }
163 22 : }
164 :
165 21 : void finalize() {
166 21 : if (LogIt::_of) { LogIt::_of.reset(); }
167 21 : }
168 :
169 : } // namespace Logging
|