QuickCppLib 0.10
Eliminate all the tedious hassle when making state-of-the-art C++ 14 - 23 libraries!
Loading...
Searching...
No Matches
quickcpplib::_xxx::ringbuffer_log::simple_ringbuffer_log_policy_detail Namespace Reference

Classes

struct  value_type
 

Typedefs

using level_ = level
 

Functions

std::string location (const value_type &v)
 Location generator for simple_ringbuffer_log_policy's value_type.
 
std::ostream & operator<< (std::ostream &s, const value_type &v)
 std::ostream writer for simple_ringbuffer_log_policy's value_type
 
std::ostream & csv (std::ostream &s, const value_type &v)
 CSV std::ostream writer for simple_ringbuffer_log_policy's value_type.
 

Typedef Documentation

◆ level_

Function Documentation

◆ location()

std::string quickcpplib::_xxx::ringbuffer_log::simple_ringbuffer_log_policy_detail::location ( const value_type v)
inline

Location generator for simple_ringbuffer_log_policy's value_type.

219 {
220 std::string ret;
221 if(v.using_backtrace)
222 {
223 void *backtrace[16];
224 memset(backtrace, 0, sizeof(backtrace));
225 size_t len = 0;
226 {
228 for(auto *i : pb)
229 {
230 backtrace[len] = i;
231 len++;
232 if(len == sizeof(backtrace) / sizeof(backtrace[0]))
233 break;
234 }
235 }
236#ifndef _WIN32
237 bool done = false;
238 // Try llvm-symbolizer for nicer backtraces
239 int temp[2];
240 struct _h
241 {
242 int fd;
243 } childreadh, childwriteh, readh, writeh;
244 if(-1 != ::pipe(temp))
245 {
246 using namespace scope;
247 childreadh.fd = temp[0];
248 readh.fd = temp[1];
249 if(-1 != ::pipe(temp))
250 {
251 writeh.fd = temp[0];
252 childwriteh.fd = temp[1];
253 auto unmypipes = make_scope_exit([&]() noexcept {
254 (void) ::close(readh.fd);
255 (void) ::close(writeh.fd);
256 });
257 auto unhispipes = make_scope_exit([&]() noexcept {
258 (void) ::close(childreadh.fd);
259 (void) ::close(childwriteh.fd);
260 });
261 (void) ::fcntl(readh.fd, F_SETFD, FD_CLOEXEC);
262 (void) ::fcntl(writeh.fd, F_SETFD, FD_CLOEXEC);
263
264 posix_spawn_file_actions_t child_fd_actions;
265 if(!::posix_spawn_file_actions_init(&child_fd_actions))
266 {
267 auto unactions = make_scope_exit([&]() noexcept { ::posix_spawn_file_actions_destroy(&child_fd_actions); });
268 if(!::posix_spawn_file_actions_adddup2(&child_fd_actions, childreadh.fd, STDIN_FILENO))
269 {
270 if(!::posix_spawn_file_actions_addclose(&child_fd_actions, childreadh.fd))
271 {
272 if(!::posix_spawn_file_actions_adddup2(&child_fd_actions, childwriteh.fd, STDOUT_FILENO))
273 {
274 if(!::posix_spawn_file_actions_addclose(&child_fd_actions, childwriteh.fd))
275 {
276 pid_t pid;
277 std::vector<const char *> argptrs(2);
278 argptrs[0] = "llvm-symbolizer";
279 if(!::posix_spawnp(&pid, "llvm-symbolizer", &child_fd_actions, nullptr, (char **) argptrs.data(), environ))
280 {
281 (void) ::close(childreadh.fd);
282 (void) ::close(childwriteh.fd);
283 std::string addrs;
284 addrs.reserve(1024);
285 for(size_t n = 0; n < len; n++)
286 {
287 Dl_info info;
288 memset(&info, 0, sizeof(info));
289 ::dladdr(backtrace[n], &info);
290 if(info.dli_fname == nullptr)
291 {
292 break;
293 }
294 // std::cerr << bt[n] << " dli_fname = " << info.dli_fname << " dli_fbase = " << info.dli_fbase
295 // << std::endl;
296 addrs.append(info.dli_fname);
297 addrs.append(" 0x");
298 const bool has_slash = (strrchr(info.dli_fname, '/') != nullptr);
299 const bool is_dll = (strstr(info.dli_fname, ".so") != nullptr);
300 if(has_slash)
301 {
302 ssize_t diff;
303 if(is_dll)
304 {
305 diff = (char *) backtrace[n] - (char *) info.dli_fbase;
306 }
307 else
308 {
309 diff = (ssize_t) backtrace[n];
310 }
311 char buffer[32];
312 snprintf(buffer, 32, "%zx", diff);
313 buffer[31] = 0;
314 addrs.append(buffer);
315 }
316 else
317 {
318 char buffer[32];
319 snprintf(buffer, 32, "%zx", (uintptr_t) backtrace[n]);
320 buffer[31] = 0;
321 addrs.append(buffer);
322 }
323 addrs.push_back('\n');
324 }
325 // std::cerr << "\n\n---\n" << addrs << "---\n\n" << std::endl;
326 // Suppress SIGPIPE
327 sigset_t toblock, oldset;
328 sigemptyset(&toblock);
329 sigaddset(&toblock, SIGPIPE);
330 pthread_sigmask(SIG_BLOCK, &toblock, &oldset);
331 auto unsigmask = make_scope_exit([&toblock, &oldset]() noexcept {
332#ifdef __APPLE__
333 pthread_kill(pthread_self(), SIGPIPE);
334 int cleared = 0;
335 sigwait(&toblock, &cleared);
336#else
337 struct timespec ts = {0, 0};
338 sigtimedwait(&toblock, 0, &ts);
339#endif
340 pthread_sigmask(SIG_SETMASK, &oldset, nullptr);
341 });
342 (void) unsigmask;
343 ssize_t written = ::write(readh.fd, addrs.data(), addrs.size());
344 (void) ::close(readh.fd);
345 addrs.clear();
346 if(written != -1)
347 {
348 char buffer[1024];
349 for(;;)
350 {
351 auto bytes = ::read(writeh.fd, buffer, sizeof(buffer));
352 if(bytes < 1)
353 break;
354 addrs.append(buffer, bytes);
355 }
356 (void) ::close(writeh.fd);
357 unmypipes.release();
358 unhispipes.release();
359 }
360 // std::cerr << "\n\n---\n" << addrs << "---\n\n" << std::endl;
361 // reap child
362 siginfo_t info;
363 memset(&info, 0, sizeof(info));
364 int options = WEXITED | WSTOPPED;
365 if(-1 == ::waitid(P_PID, pid, &info, options))
366 abort();
367 if(!addrs.empty())
368 {
369 // We want the second line from every section separated by a double newline
370 size_t n = 0;
371 auto printitem = [&](size_t idx) {
372 if(n)
373 ret.append(", ");
374 auto idx2 = addrs.find(10, idx), idx3 = addrs.find(10, idx2 + 1);
375 ret.append(addrs.data() + idx2 + 1, idx3 - idx2 - 1);
376 n++;
377 };
378 size_t oldidx = 0;
379 for(size_t idx = addrs.find("\n\n"); idx != std::string::npos; oldidx = idx + 2, idx = addrs.find("\n\n", idx + 1))
380 {
381 printitem(oldidx);
382 }
383 done = true;
384 }
385 }
386 }
387 }
388 }
389 }
390 }
391 }
392 }
393 if(!done)
394#endif
395
396 {
397#if !QUICKCPPLIB_DISABLE_EXECINFO
398 char **symbols = backtrace_symbols(backtrace, len);
399 if(!symbols)
400 ret.append("BACKTRACE FAILED!");
401 else
402 {
403 for(size_t n = 0; n < len; n++)
404 {
405 if(symbols[n])
406 {
407 if(n)
408 ret.append(", ");
409 ret.append(symbols[n]);
410 }
411 }
412 free(symbols);
413 }
414#endif
415 }
416 }
417 else
418 {
419 char temp[256];
420 memcpy(temp, v.function, sizeof(v.function));
421 temp[sizeof(v.function)] = 0;
422 ret.append(temp);
423 }
424 return ret;
425 }
A space packed stack backtrace letting you store twice or more stack frames in the same space.
Definition packed_backtrace.hpp:548
EXECINFO_DECL _Check_return_ _In_ size_t len
Definition execinfo_win64.h:55
EXECINFO_DECL _Check_return_ size_t backtrace(_Out_writes_(len) void **bt, _In_ size_t len)
Fill the array of void * at bt with up to len entries, returning entries filled.
constexpr auto make_scope_exit(T &&v)
Definition scope.hpp:153

◆ operator<<()

std::ostream & quickcpplib::_xxx::ringbuffer_log::simple_ringbuffer_log_policy_detail::operator<< ( std::ostream &  s,
const value_type v 
)
inline

std::ostream writer for simple_ringbuffer_log_policy's value_type

428 {
429 s << "+" << std::setfill('0') << std::setw(16) << v.timestamp << " " << std::setfill(' ') << std::setw(1);
430 switch(v.level)
431 {
432 case 0:
433 s << "none: ";
434 break;
435 case 1:
436 s << "fatal: ";
437 break;
438 case 2:
439 s << "error: ";
440 break;
441 case 3:
442 s << "warn: ";
443 break;
444 case 4:
445 s << "info: ";
446 break;
447 case 5:
448 s << "debug: ";
449 break;
450 case 6:
451 s << "all: ";
452 break;
453 default:
454 s << "unknown: ";
455 break;
456 }
457 if(v.using_code64)
458 s << "{ " << v.code64 << " } ";
459 else
460 s << "{ " << v.code32[0] << ", " << v.code32[1] << " } ";
461 char temp[256];
462 memcpy(temp, v.message, sizeof(v.message));
463 temp[sizeof(v.message)] = 0;
464 s << temp << " @ ";
465 s << location(v);
466 return s << "\n";
467 }

◆ csv()

std::ostream & quickcpplib::_xxx::ringbuffer_log::simple_ringbuffer_log_policy_detail::csv ( std::ostream &  s,
const value_type v 
)
inline

CSV std::ostream writer for simple_ringbuffer_log_policy's value_type.

470 {
471 // timestamp,level,using_code64,using_backtrace,code0,code1,message,backtrace
472 s << v.timestamp << "," << (unsigned) v.level << "," << (unsigned) v.using_code64 << "," << (unsigned) v.using_backtrace << ",";
473 if(v.using_code64)
474 s << v.code64 << ",0,\"";
475 else
476 s << v.code32[0] << "," << v.code32[1] << ",\"";
477 char temp[256];
478 memcpy(temp, v.message, sizeof(v.message));
479 temp[sizeof(v.message)] = 0;
480 s << temp << "\",\"";
481 if(v.using_backtrace)
482 {
483#if !QUICKCPPLIB_DISABLE_EXECINFO
484 char **symbols = backtrace_symbols((void **) v.backtrace, sizeof(v.backtrace) / sizeof(v.backtrace[0]));
485 if(!symbols)
486 s << "BACKTRACE FAILED!";
487 else
488 {
489 for(size_t n = 0; n < sizeof(v.backtrace) / sizeof(v.backtrace[0]); n++)
490 {
491 if(symbols[n])
492 {
493 if(n)
494 s << ";";
495 s << symbols[n];
496 }
497 }
498 free(symbols);
499 }
500#endif
501 }
502 else
503 {
504 memcpy(temp, v.function, sizeof(v.function));
505 temp[sizeof(v.function)] = 0;
506 s << temp;
507 }
508 return s << "\"\n";
509 }