• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 21047054485

15 Jan 2026 09:31PM UTC coverage: 60.507% (-0.001%) from 60.508%
21047054485

push

github

web-flow
Clang Tidy default constructor  (#852)

* trigger clang tidy

* Automated clang-tidy change: modernize-use-equals-default

* compile test

---------

Co-authored-by: Clang Tidy <clang-tidy@users.noreply.github.com>

58 of 75 new or added lines in 41 files covered. (77.33%)

1 existing line in 1 file now uncovered.

44460 of 73479 relevant lines covered (60.51%)

507363.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

9.62
/pol-core/clib/Debugging/ExceptionParser.cpp
1
#include "ExceptionParser.h"
2

3
#include "../Program/ProgramConfig.h"
4
#include "../logfacility.h"
5
#include "../stlutil.h"
6
#include "../threadhelp.h"
7
#include "pol_global_config.h"
8

9
#include <cstddef>
10
#include <cstdlib>
11
#include <cstring>
12
#include <errno.h>
13
#include <signal.h>
14
#include <stdio.h>
15

16
#ifndef WINDOWS
17
#include <arpa/inet.h>
18
#include <cxxabi.h>
19
#include <execinfo.h>
20
#include <netdb.h>
21
#include <netinet/in.h>
22
#include <sys/mman.h>
23
#include <unistd.h>
24

25
#define SOCKET int
26
#else
27
#include "../Header_Windows.h"
28
#include "shlwapi.h"
29
#endif
30

31
#include <boost/stacktrace.hpp>
32

33
#define MAX_STACK_TRACE_DEPTH 200
34
#define MAX_STACK_TRACE_STEP_LENGTH 512
35

36
namespace Pol
37
{
38
namespace Clib
39
{
40
using namespace std;
41

42
///////////////////////////////////////////////////////////////////////////////
43

44
bool ExceptionParser::m_programAbortReporting = false;
45
std::string ExceptionParser::m_programAbortReportingServer = "";
46
std::string ExceptionParser::m_programAbortReportingUrl = "";
47
std::string ExceptionParser::m_programAbortReportingReporter = "";
48
std::string ExceptionParser::m_programStart = Pol::Clib::Logging::LogSink::getTimeStamp();
49

50
///////////////////////////////////////////////////////////////////////////////
51

52
namespace
53
{
54
void getSignalDescription( int signal, string& signalName, string& signalDescription )
×
55
{
56
  switch ( signal )
×
57
  {
58
  case 1:
×
59
    signalName = "SIGHUP";
×
60
    signalDescription = "hangup detected on controlling terminal or death of controlling process";
×
61
    break;
×
62
  case 2:
×
63
    signalName = "SIGINT";
×
64
    signalDescription = "interrupt from keyboard";
×
65
    break;
×
66
  case 3:
×
67
    signalName = "SIGQUIT";
×
68
    signalDescription = "quit from keyboard";
×
69
    break;
×
70
  case 4:
×
71
    signalName = "SIGILL";
×
72
    signalDescription = "illegal Instruction";
×
73
    break;
×
74
  case 6:
×
75
    signalName = "SIGABRT";
×
76
    signalDescription = "abort signal from abort()";
×
77
    break;
×
78
  case 8:
×
79
    signalName = "SIGFPE";
×
80
    signalDescription = "floating point exception";
×
81
    break;
×
82
  case 9:
×
83
    signalName = "SIGKILL";
×
84
    signalDescription = "kill signal";
×
85
    break;
×
86
  case 10:
×
87
    signalName = "SIGBUS";
×
88
    signalDescription = "bus error";
×
89
    break;
×
90
  case 11:
×
91
    signalName = "SIGSEGV";
×
92
    signalDescription = "invalid memory reference";
×
93
    break;
×
94
  case 12:
×
95
    signalName = "SIGSYS";
×
96
    signalDescription = "bad argument to system call";
×
97
    break;
×
98
  case 13:
×
99
    signalName = "SIGPIPE";
×
100
    signalDescription = "broken pipe: write to pipe with no readers";
×
101
    break;
×
102
  case 14:
×
103
    signalName = "SIGALRM";
×
104
    signalDescription = "timer signal from alarm()";
×
105
    break;
×
106
  case 15:
×
107
    signalName = "SIGTERM";
×
108
    signalDescription = "termination signal";
×
109
    break;
×
110
  case 18:
×
111
    signalName = "SIGCONT";
×
112
    signalDescription = "continue signal from tty";
×
113
    break;
×
114
  case 19:
×
115
    signalName = "SIGSTOP";
×
116
    signalDescription = "stop signal from tty";
×
117
    break;
×
118
  case 20:
×
119
    signalName = "SIGTSTP";
×
120
    signalDescription = "stop signal from user (keyboard)";
×
121
    break;
×
122
  case 16:
×
123
  case 30:
124
    signalName = "SIGUSR1";
×
125
    signalDescription = "user-defined signal 1";
×
126
    break;
×
127
  case 17:
×
128
  case 31:
129
    signalName = "SIGUSR2";
×
130
    signalDescription = "user-defined signal 2";
×
131
    break;
×
132
  default:
×
133
    signalName = "unsupported signal";
×
134
    signalDescription = "unsupported signal occurred";
×
135
    break;
×
136
  }
137
}
×
138

139
#if !defined( _WIN32 ) && !defined( __APPLE__ )
140
void logExceptionSignal( int signal )
×
141
{
142
  string signalName;
×
143
  string signalDescription;
×
144

145
  getSignalDescription( signal, signalName, signalDescription );
×
146
  printf( "Signal \"%s\"(%d: %s) detected.\n", signalName.c_str(), signal,
×
147
          signalDescription.c_str() );
148
}
×
149
#endif
150

151
string getCompilerVersion()
×
152
{
153
#ifdef LINUX
154
  char result[256];
155
#ifdef __clang__
156
  snprintf( result, arsize( result ), "clang %d.%d.%d", __clang_major__, __clang_minor__,
157
            __clang_patchlevel__ );
158
#else
159
  snprintf( result, arsize( result ), "gcc %d.%d.%d", __GNUC__, __GNUC_MINOR__,
×
160
            __GNUC_PATCHLEVEL__ );
161
#endif
162
#endif
163
#ifdef WINDOWS
164
  string result;
165
  switch ( _MSC_VER )
166
  {
167
  case 1900:
168
    result = "MSVC++ 14.0 (Visual Studio 2015)";
169
    break;
170
  case 1800:
171
    result = "MSVC++ 12.0 (Visual Studio 2013)";
172
    break;
173
  case 1700:
174
    result = "MSVC++ 11.0 (Visual Studio 2012)";
175
    break;
176
  case 1600:
177
    result = "MSVC++ 10.0 (Visual Studio 2010)";
178
    break;
179
  case 1500:
180
    result = "MSVC++ 9.0 (Visual Studio 2008)";
181
    break;
182
  case 1400:
183
    result = "MSVC++ 8.0 (Visual Studio 2005)";
184
    break;
185
  case 1310:
186
    result = "MSVC++ 7.1 (Visual Studio 2003)";
187
    break;
188
  case 1300:
189
    result = "MSVC++ 7.0";
190
    break;
191
  case 1200:
192
    result = "MSVC++ 6.0";
193
    break;
194
  case 1100:
195
    result = "MSVC++ 5.0";
196
    break;
197
  default:
198
#if ( _MSC_VER > 1800 )
199
    result = "MSVC++ newer than version 12.0";
200
#elif ( _MSC_VER < 1100 )
201
    result = "MSVC++ older than version 5.0";
202
#else
203
    result = "MSVC++ (some unsupported version)";
204
#endif
205
    break;
206
  }
207
#endif
208

209
  return result;
×
210
}
211

212
void doHttpPOST( const string& host, const string& url, const string& content )
×
213
{
214
#define MAXLINE 4096
215
  char request[MAXLINE + 1];
216
  SOCKET socketFD;
217
  char targetIP[INET6_ADDRSTRLEN];
218

219
/**
220
 * prepare the request
221
 */
222
#ifdef _MSC_VER
223
  _snprintf(
224
#else
225
  snprintf(
×
226
#endif
227
      request, MAXLINE,
228
      "POST %s HTTP/1.0\r\n"
229
      "Host: %s\r\n"
230
      "Content-Type: application/x-www-form-urlencoded\r\n"
231
      "User-Agent: POL in-app abort reporting system, %s\r\n"
232
      "Content-length: %d\r\n\r\n"
233
      "%s",
234
      url.c_str(), host.c_str(), POL_VERSION_ID, (int)content.size(), content.c_str() );
×
235

236
  /**
237
   * DNS lookup if needed
238
   */
239
  struct addrinfo* serverAddr;
240
  struct addrinfo hints;
241
  memset( &hints, 0, sizeof hints );
×
242
  hints.ai_family = AF_UNSPEC;  // IPv4 or IPv6
×
243
  hints.ai_flags = AI_ADDRCONFIG;
×
244
  hints.ai_socktype = SOCK_STREAM;
×
245
  int res = getaddrinfo( host.c_str(), "http", &hints, &serverAddr );
×
246
  if ( res != 0 )
×
247
  {
248
    fprintf( stderr, "getaddrinfo() failed for \"%s\" due to \"%s\"(code: %d)\n", host.c_str(),
×
249
             gai_strerror( res ), res );
250
    std::_Exit( 1 );
×
251
  }
252

253
  switch ( serverAddr->ai_addr->sa_family )
×
254
  {
255
  case AF_INET:
×
256
    if ( inet_ntop( AF_INET, &( (struct sockaddr_in*)serverAddr->ai_addr )->sin_addr, targetIP,
×
257
                    INET_ADDRSTRLEN ) == nullptr )
×
258
      std::_Exit( 1 );
×
259
    break;
×
260

261
  case AF_INET6:
×
262
    if ( inet_ntop( AF_INET6, &( (struct sockaddr_in*)serverAddr->ai_addr )->sin_addr, targetIP,
×
263
                    INET6_ADDRSTRLEN ) == nullptr )
×
264
      std::_Exit( 1 );
×
265
    break;
×
266

267
  default:
×
268
    fprintf( stderr, "Unknown address family found for %s\n", host.c_str() );
×
269
    std::_Exit( 1 );
×
270
  }
271

272
  // create the socket
273
  socketFD = socket( serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol );
×
274

275
  /**
276
   * connect to the bug tracking server
277
   */
278
  if ( ( res = connect( socketFD, serverAddr->ai_addr, (int)serverAddr->ai_addrlen ) ) != 0 )
×
279
  {
280
    fprintf( stderr, "connect() failed for server \"%s\"(IP: %s) due \"%s\"(%d)\n", host.c_str(),
×
281
             targetIP, strerror( errno ), errno );
×
282
    std::_Exit( 1 );
×
283
  }
284

285
  freeaddrinfo( serverAddr );  // not needed anymore
×
286

287
/**
288
 * send the request
289
 */
290
#if !defined( _WIN32 ) && !defined( __APPLE__ )
291
  send( socketFD, request, strlen( request ), MSG_NOSIGNAL );
×
292
#else
293
  send( socketFD, request, (int)strlen( request ), 0 );
294
#endif
295
  printf( "Abort report was sent to %s%s (IP: %s)\n", host.c_str(), url.c_str(), targetIP );
×
296

297
  /**
298
   * wait for some answers and print them on the screen
299
   */
300
  ssize_t readBytes;
301
  char answer[MAXLINE + 1];
302

303
#if !defined( _WIN32 ) && !defined( __APPLE__ )
304
  while ( ( readBytes = recv( socketFD, answer, MAXLINE, MSG_NOSIGNAL ) ) > 0 )
×
305
  {
306
#else
307
  while ( ( readBytes = recv( socketFD, answer, MAXLINE, 0 ) ) > 0 )
308
  {
309
#endif
310
    answer[readBytes] = '\0';
×
311
    printf( "Answer from bug tracking server:\n%s\n", answer );
×
312
    // skip the received answer and proceed
313
  }
314

315
// close the socket to the bug tracking server
316
#ifndef _WIN32
317
  close( socketFD );
×
318
#else
319
  closesocket( socketFD );
320
#endif
321
}
×
322
}  // namespace
323

324
void ExceptionParser::reportProgramAbort( const string& stackTrace, const string& reason )
×
325
{
326
  /**
327
   * set some default values if the abort occurs too early and pol.cfg wasn't parsed yet
328
   */
329
  string host = "polserver.com";
×
330
  string url = "/pol/report_program_abort.php";
×
331
  if ( ( m_programAbortReportingServer.c_str() != nullptr ) &&
×
332
       ( m_programAbortReportingServer != "" ) )
×
333
  {
334
    host = m_programAbortReportingServer;
×
335
    if ( m_programAbortReportingUrl.c_str() != nullptr )
×
336
      url = m_programAbortReportingUrl;
×
337
  }
338

339
  // create the abort description for the subsequent POST request
340
  string content = "email=" + m_programAbortReportingReporter +
×
341
                   "&"
342
                   "bin=" +
×
343
                   PROG_CONFIG::programName() +
×
344
                   "&"
345
                   "start_time=" +
×
346
                   m_programStart +
×
347
                   "&"
348
                   "abort_time=" +
×
349
                   Pol::Clib::Logging::LogSink::getTimeStamp() +
×
350
                   "&"
351
                   "reason=" +
×
352
                   reason +
×
353
                   "&"
354
                   "trace=" +
×
355
                   stackTrace +
×
356
                   "&"
357
                   "comp=" +
×
358
                   getCompilerVersion() +
×
359
                   "&"
360
                   "comp_time=" +
×
361
                   ProgramConfig::build_datetime() +
×
362
                   "&"
363
                   "build_target=" +
×
364
                   ProgramConfig::build_target() +
×
365
                   "&"
366
                   "build_revision=" POL_VERSION_ID
367
                   "&"
368
                   "misc=";
×
369

370
  // execute the POST request
371
  doHttpPOST( host, url, content );
×
372
}
×
373

374
void ExceptionParser::handleExceptionSignal( int signal )
×
375
{
376
  switch ( signal )
×
377
  {
378
  case SIGILL:
×
379
  case SIGFPE:
380
  case SIGSEGV:
381
  case SIGTERM:
382
  case SIGABRT:
383
  {
384
    /**
385
     * inform the user about the program abort
386
     */
387
    printf(
×
388
        "########################################################################################"
389
        "\n" );
390
    if ( m_programAbortReporting )
×
391
      printf( "POL will exit now. The following will be sent to the POL developers:\n\n" );
×
392
    else
393
      printf(
×
394
          "POL will exit now. Please, post the following to the forum: "
395
          "http://forums.polserver.com/.\n" );
396
    string tStackTrace = ExceptionParser::getTrace();
×
397
    printf( "%s", tStackTrace.c_str() );
×
398
    printf( "Admin contact: %s\n", m_programAbortReportingReporter.c_str() );
×
399
    printf( "Executable: %s\n", PROG_CONFIG::programName().c_str() );
×
400
    printf( "Start time: %s\n", m_programStart.c_str() );
×
401
    printf( "Current time: %s\n", Pol::Clib::Logging::LogSink::getTimeStamp().c_str() );
×
402
    printf( "\n" );
×
403
    printf( "Stack trace:\n%s", tStackTrace.c_str() );
×
404
    printf( "\n" );
×
405
    printf( "Compiler: %s\n", getCompilerVersion().c_str() );
×
406
    printf( "Compile time: %s\n", ProgramConfig::build_datetime().c_str() );
×
407
    printf( "Build target: %s\n", ProgramConfig::build_target().c_str() );
×
408
    printf( "Build revision: %s\n", POL_VERSION_ID );
×
409
#if defined( __GLIBC__ )
410
    printf( "GNU C library (compile time): %d.%d\n", __GLIBC__, __GLIBC_MINOR__ );
×
411
#endif
412
    printf( "\n" );
×
413
    printf(
×
414
        "########################################################################################"
415
        "\n" );
416
    fflush( stdout );
×
417

418
    /**
419
     * use the program abort reporting system
420
     */
421
    if ( m_programAbortReporting )
×
422
    {
423
      string signalName;
×
424
      string signalDescription;
×
425

426
      getSignalDescription( signal, signalName, signalDescription );
×
427
      ExceptionParser::reportProgramAbort(
×
428
          tStackTrace, "CRASH caused by signal " + signalName + " (" + signalDescription + ")" );
×
429
    }
×
430

431
    // finally, go to hell
432
    std::_Exit( 1 );
×
433
  }
×
434
  break;
435
  default:
×
436
    break;
×
437
  }
438
}
×
439

440
///////////////////////////////////////////////////////////////////////////////
441

NEW
442
ExceptionParser::ExceptionParser() = default;
×
443

444
ExceptionParser::~ExceptionParser() {}
×
445

446
///////////////////////////////////////////////////////////////////////////////
447

448
#if !defined( _WIN32 ) && !defined( __APPLE__ )
449
static void handleSignalLinux( int signal, siginfo_t* signalInfo, void* arg )
×
450
{
451
  (void)arg;
452
  logExceptionSignal( signal );
×
453
  if ( signalInfo != nullptr )
×
454
  {
455
    if ( signal == SIGSEGV )
×
456
    {
457
      if ( signalInfo->si_addr != nullptr )
×
458
        printf( "Segmentation fault detected - faulty memory reference at location: %p\n",
×
459
                signalInfo->si_addr );
460
      else
461
        printf( "Segmentation fault detected - null pointer reference\n" );
×
462
    }
463
    if ( signalInfo->si_errno != 0 )
×
464
      printf( "This signal occurred because \"%s\"(%d)\n", strerror( signalInfo->si_errno ),
×
465
              signalInfo->si_errno );
466
    if ( signalInfo->si_code != 0 )
×
467
      printf( "Signal code is %d\n", signalInfo->si_code );
×
468
  }
469
  ExceptionParser::handleExceptionSignal( signal );
×
470
}
×
471

472
static void handleStackTraceRequestLinux( int signal, siginfo_t* signalInfo, void* arg )
×
473
{
474
  (void)signal;
475
  (void)signalInfo;
476
  (void)arg;
477
  threadhelp::ThreadMap::Contents threadDesc;
×
478
  threadhelp::threadmap.CopyContents( threadDesc );
×
479

480
  std::string output = fmt::format( "STACK TRACE for thread \"{}\"({}):\n",
481
                                    threadDesc[pthread_self()], pthread_self() );
×
482
  output += ExceptionParser::getTrace() + '\n';
×
483

484
  // print to stdout
485
  printf( "%s", output.c_str() );
×
486

487
  // print to error output
488
  POLLOG_ERROR( output );
×
489

490
  // wait here for logging facility to make sure everything was processed
491
  if ( Clib::Logging::global_logger )
×
492
    Clib::Logging::global_logger->wait_for_empty_queue();
×
493
}
×
494

495
void ExceptionParser::logAllStackTraces()
×
496
{
497
  threadhelp::ThreadMap::Contents threadsDesc;
×
498
  threadhelp::threadmap.CopyContents( threadsDesc );
×
499
  for ( const auto& threadDesc : threadsDesc )
×
500
  {
501
    pthread_t threadID = (pthread_t)threadDesc.first;
×
502

503
    if ( pthread_kill( threadID, SIGUSR1 ) != 0 )
×
504
    {
505
      fprintf( stderr, "%s",
×
506
               fmt::format( "pthread_kill() failed to send SIGUSR1 to thread {}({})\n",
×
507
                            threadsDesc[threadID], threadID )
×
508
                   .c_str() );
509
    }
510
  }
511
}
×
512

513
void ExceptionParser::initGlobalExceptionCatching()
4,959✔
514
{
515
  struct sigaction sigAction;
516

517
  memset( &sigAction, 0, sizeof( sigAction ) );
4,959✔
518
  sigemptyset( &sigAction.sa_mask );
4,959✔
519
  sigAction.sa_sigaction = handleSignalLinux;
4,959✔
520
  sigAction.sa_flags = SA_SIGINFO;
4,959✔
521
  sigaction( SIGINT, &sigAction, nullptr );
4,959✔
522
  sigaction( SIGTERM, &sigAction, nullptr );
4,959✔
523
  sigaction( SIGSEGV, &sigAction, nullptr );
4,959✔
524
  sigaction( SIGABRT, &sigAction, nullptr );
4,959✔
525
  sigAction.sa_sigaction = handleStackTraceRequestLinux;
4,959✔
526
  sigaction( SIGUSR1, &sigAction, nullptr );
4,959✔
527

528
  // set handler stack
529
  stack_t tStack;
530
  // mmap: no false positives for leak, plus guardpages to get SIGSEGV on memory overwrites
531
  char* mem = static_cast<char*>( mmap( nullptr, SIGSTKSZ + 2 * getpagesize(),
4,959✔
532
                                        PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0 ) );
533
  mprotect( mem, getpagesize(), PROT_NONE );
4,959✔
534
  mprotect( mem + getpagesize() + SIGSTKSZ, getpagesize(), PROT_NONE );
4,959✔
535
  tStack.ss_sp = mem + getpagesize();
4,959✔
536
  tStack.ss_size = SIGSTKSZ;
4,959✔
537
  tStack.ss_flags = 0;
4,959✔
538
  if ( sigaltstack( &tStack, nullptr ) == -1 )
4,959✔
539
  {
540
    printf( "Could not set signal handler stack\n" );
×
541
    std::exit( 1 );
×
542
  }
543
}
4,959✔
544
#else  // _WIN32 || Apple
545

546
void ExceptionParser::logAllStackTraces() {}
547

548
void ExceptionParser::initGlobalExceptionCatching()
549
{
550
#if defined( _WIN32 )
551
  // see compile_defs.cmake
552
  // in addition add the executable path as searchpath
553
  wchar_t path[MAX_PATH];
554
  GetModuleFileNameW( nullptr, path, MAX_PATH );
555
  PathRemoveFileSpecW( path );
556
  SetEnvironmentVariableW( L"_NT_ALT_SYMBOL_PATH", path );
557
#endif
558
}
559
#endif  // _WIN32 || Apple
560

561
string ExceptionParser::getTrace()
×
562
{
563
  auto stack = boost::stacktrace::stacktrace::from_current_exception();
×
564
  // current_exception does not always work, eg no active exception
565
  // and needs linking with libboost_stacktrace_backtrace, which as of now is not possible with
566
  // Apple. Current stacktrace as fallback, which should give enough infos
567
  if ( stack.empty() )
×
568
    stack = boost::stacktrace::stacktrace();
×
569
  return boost::stacktrace::to_string( stack );
×
570
}
×
571

572
void ExceptionParser::configureProgramAbortReportingSystem( bool active, std::string server,
39✔
573
                                                            std::string url, std::string reporter )
574
{
575
  m_programAbortReporting = active;
39✔
576
  m_programAbortReportingServer = std::move( server );
39✔
577
  m_programAbortReportingUrl = std::move( url );
39✔
578
  m_programAbortReportingReporter = std::move( reporter );
39✔
579
}
39✔
580

581
bool ExceptionParser::programAbortReporting()
×
582
{
583
  return m_programAbortReporting;
×
584
}
585

586
///////////////////////////////////////////////////////////////////////////////
587
}  // namespace Clib
588
}  // namespace Pol
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc