message: Improve multi-thread assertion failures
  Summary: On Linux, put all but the first failing threads to sleep. This ensures a cleaner abort.
diff: #include "Debug.h"
  +#include <atomic>
  #include <exception>
  #include <fstream>
  #include <iomanip>
  #include <unistd.h>
  #endif
  +#ifdef __linux__
  +#include <sys/syscall.h>
  +#include <sys/types.h>
  +#include <unistd.h>
  +#endif
  +
  #include <boost/algorithm/string.hpp>
  #include <boost/exception/all.hpp>
  #ifdef __APPLE__
  @@ -77,6 +84,11 @@ namespace {
  using traced =
  boost::error_info<struct tag_stacktrace, boost::stacktrace::stacktrace>;
  +#ifdef __linux__
  +std::atomic<pid_t> g_aborting{0};
  +pid_t get_tid() { return syscall(SYS_gettid); }
  +#endif
  +
  } // namespace
  void assert_fail(const char* expr,
  @@ -94,10 +106,31 @@ void assert_fail(const char* expr,
  msg += v_format2string(fmt, ap);
  va_end(ap);
  +
  + bool do_throw;
  +#ifdef __linux__
  + pid_t cur = get_tid();
  + pid_t expected = 0;
  + do_throw = g_aborting.compare_exchange_strong(expected, cur);
  + if (!do_throw) {
  + do_throw = expected == cur;
  + }
  +#else
  + do_throw = true;
  +#endif
  +
  + if (do_throw) {
  throw boost::enable_error_info(RedexException(type, msg))
  << traced(boost::stacktrace::stacktrace());
  }
  + // Another thread already threw. Avoid "terminate called recursively."
  + // Infinite loop.
  + for (;;) {
  + sleep(1000);
  + }
  +}
  +
  void print_stack_trace(std::ostream& os, const std::exception& e) {
  const boost::stacktrace::stacktrace* st = boost::get_error_info<traced>(e);
  if (st) {
  