@@ -195,7 +195,7 @@ void *mainloop_udata;
195195extern " C" int _fltused = 0 ;
196196#endif
197197
198- static struct backtrace_state *bs ;
198+ static struct backtrace_state *bt ;
199199
200200struct init_data {
201201 bool com_initialized = false ;
@@ -438,42 +438,52 @@ static void echeck_unexpected_exit(void ) {
438438
439439#ifdef HAVE_LIBBACKTRACE
440440static void
441- error_callback (void *data, const char *msg, int errnum)
441+ libbt_error_callback (void *data, const char *msg, int errnum)
442442{
443+ int fd = *reinterpret_cast <int *>(data);
444+ char buf[STR_LEN];
445+ char *start = buf;
446+ const char *const end = buf + sizeof buf;
447+
443448 // fprintf(stderr, "libbacktrace error: %s (%d)\n", msg, errnum);
444449
445- int fd = *reinterpret_cast <int *>(data);
446- char buf[] = " libbacktrace error: " ;
447- write_all (fd, sizeof buf - 1 , buf);
448- write_all (fd, strlen (msg), msg);
449- write_all (fd, 2 , " (" );
450- write_number (fd, errnum);
451- write_all (fd, 2 , " )\n " );
450+ strappend (&start, end, " libbacktrace error: " );
451+ strappend (&start, end, msg);
452+ strappend (&start, end, " (" );
453+ append_number (&start, end, errnum);
454+
455+ write_all (fd, start - buf, buf);
452456}
453457
454458static int
455- full_callback (void *data, uintptr_t pc, const char *filename, int lineno,
459+ libbt_full_callback (void *data, uintptr_t pc, const char *filename, int lineno,
456460 const char *function)
457461{
462+ int fd = *reinterpret_cast <int *>(data);
463+ char buf[STR_LEN];
464+ char *start = buf;
465+ const char *const end = buf + sizeof buf;
466+
458467 // printf(" %s at %s:%d [pc=%p]\n", function ? function : "??",
459468 // filename ? filename : "??", lineno, (void *) pc);
460469
461- int fd = *reinterpret_cast <int *>(data);
462- write_all (fd, 2 , " " );
470+ strappend (&start, end, " " );
463471 if (function == nullptr ) {
464472 function = " ??" ;
465473 }
466- write_all (fd, strlen (function) , function);
467- write_all (fd, 4 , " at " );
474+ strappend (&start, end , function);
475+ strappend (&start, end , " at " );
468476 if (filename == nullptr ) {
469477 filename = " ??" ;
470478 }
471- write_all (fd, strlen (filename), filename);
472- write_all (fd, 1 , " :" );
473- write_number (fd, lineno);
474- write_all (fd, 7 , " [pc=0x" );
475- write_number (fd, (uintmax_t ) pc);
476- write_all (fd, 2 , " ]\n " );
479+ strappend (&start, end, filename);
480+ strappend (&start, end, " :" );
481+ append_number (&start, end, lineno);
482+ strappend (&start, end, " [pc=0x" );
483+ append_number (&start, end, (uintmax_t ) pc);
484+ strappend (&start, end, " ]\n " );
485+
486+ write_all (fd, start - buf, buf);
477487
478488 return 0 ; // continue
479489}
@@ -580,8 +590,8 @@ struct init_data *common_preinit(int argc, char *argv[])
580590
581591#ifdef HAVE_LIBBACKTRACE
582592 int fd = STDERR_FILENO;
583- bs = backtrace_create_state (uv_argv[0 ], 1 /* thread safe*/ ,
584- error_callback , &fd);
593+ bt = backtrace_create_state (uv_argv[0 ], 1 /* thread safe*/ ,
594+ libbt_error_callback , &fd);
585595#endif
586596
587597 atexit (echeck_unexpected_exit);
@@ -1255,6 +1265,30 @@ bool running_in_debugger(){
12551265}
12561266
12571267#if defined(__GLIBC__)
1268+ // / dumps output of fd (from start_off offset) to stderr
1269+ // / and keep the pointer at the end of the file
1270+ // / @retval size of the file pointed by fd (current pos)
1271+ static off_t
1272+ st_glibc_flush_output (int fd, off_t start_off)
1273+ {
1274+ if (fd == STDERR_FILENO) {
1275+ return 0 ;
1276+ }
1277+
1278+ lseek (fd, start_off, SEEK_SET);
1279+ char buf[STR_LEN];
1280+ ssize_t rbytes = 0 ;
1281+ while ((rbytes = read (fd, buf, sizeof buf)) > 0 ) {
1282+ ssize_t written = 0 ;
1283+ ssize_t wbytes = 0 ;
1284+ while (written < rbytes &&
1285+ (wbytes = write (STDERR_FILENO, buf + written,
1286+ rbytes - written)) > 0 ) {
1287+ written += wbytes;
1288+ }
1289+ }
1290+ return lseek (fd, 0 , SEEK_CUR);
1291+ }
12581292/* *
12591293 * print stacktrace with backtrace_symbols_fd() (glibc or macOS)
12601294 *
@@ -1276,16 +1310,13 @@ print_stacktrace_glibc()
12761310 unsigned long tid = syscall (__NR_gettid);
12771311#endif
12781312 // snprintf(path, sizeof path, "%s/ug-%lu", get_temp_dir(), tid);
1279- strncpy (path, get_temp_dir (), sizeof path) ;
1313+ char *start = path;
12801314 path[sizeof path - 1 ] = ' \0 ' ;
1281- strncat (path + strlen (path), " /ug-bt-" , sizeof path - strlen (path) - 1 );
1282- while (tid != 0 && strlen (path) < sizeof path - 1 ) {
1283- // (tid will be actually printed in reversed order (123->321))
1284- size_t len = strlen (path);
1285- path[len] = ' 0' + tid % 10 ;
1286- path[len + 1 ] = ' \0 ' ;
1287- tid /= 10 ;
1288- }
1315+ const char *const end = path + sizeof path - 1 ;
1316+ strappend (&start, end, get_temp_dir ());
1317+ strappend (&start, end, " /ug-bt-" );
1318+ append_number (&start, end, tid);
1319+ *start = ' \0 ' ;
12891320 int fd = open (path, O_CLOEXEC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
12901321 unlink (path);
12911322#endif
@@ -1298,46 +1329,36 @@ print_stacktrace_glibc()
12981329 const int num_symbols = backtrace (addresses.data (), addresses.size ());
12991330 backtrace_symbols_fd (addresses.data (), num_symbols, fd);
13001331
1332+ // in case that the below fails, try write at least something
1333+ off_t last_pos = st_glibc_flush_output (fd, 0 );
1334+
13011335#ifdef HAVE_LIBBACKTRACE
13021336 char backtrace2_msg[] = " \n Backtrace symbolic:\n " ;
13031337 write_all (fd, sizeof backtrace2_msg - 1 , backtrace2_msg);
13041338 for (int i = 0 ; i < num_symbols; i++) {
1305- char sym_nr[5 ];
1339+ // printf("%2d: ", i);
1340+ enum { NDIGITS = 2 };
1341+ char sym_nr[] = { ' X' , ' X' , ' :' , ' ' };
13061342 int num_tmp = i;
1307- for (int i = 0 ; i < 3 ; ++i) {
1343+ for (int i = 0 ; i < NDIGITS ; ++i) {
13081344 if (num_tmp == 0 && i != 0 ) {
1309- sym_nr[2 - i] = ' ' ;
1345+ sym_nr[NDIGITS - 1 - i] = ' ' ;
13101346 } else {
1311- sym_nr[2 - i] = ' 0' + (num_tmp % 10 );
1347+ sym_nr[NDIGITS - 1 - i] = ' 0' + (num_tmp % 10 );
13121348 num_tmp /= 10 ;
13131349 }
13141350 }
1315- sym_nr[3 ] = ' :' ;
1316- sym_nr[4 ] = ' ' ;
13171351 write_all (fd, sizeof sym_nr, sym_nr);
1318- // printf("%3d: ", i);
1319- backtrace_pcinfo (bs , (uintptr_t ) addresses[i], full_callback ,
1320- error_callback , &fd);
1352+ // backtrace_pcinfo may not be async-signal-safe
1353+ backtrace_pcinfo (bt , (uintptr_t ) addresses[i], libbt_full_callback ,
1354+ libbt_error_callback , &fd);
13211355 }
1356+ st_glibc_flush_output (fd, last_pos);
13221357#endif
13231358
1324- if (fd == STDERR_FILENO) {
1325- return ;
1326- }
1327-
1328- lseek (fd, 0 , SEEK_SET);
1329- char buf[STR_LEN];
1330- ssize_t rbytes = 0 ;
1331- while ((rbytes = read (fd, buf, sizeof buf)) > 0 ) {
1332- ssize_t written = 0 ;
1333- ssize_t wbytes = 0 ;
1334- while (written < rbytes &&
1335- (wbytes = write (STDERR_FILENO, buf + written,
1336- rbytes - written)) > 0 ) {
1337- written += wbytes;
1338- }
1359+ if (fd != STDERR_FILENO) {
1360+ close (fd);
13391361 }
1340- close (fd);
13411362}
13421363#endif // defined(__GLIBC__)
13431364
0 commit comments