#define __ABORT_NOW(file, line, ...) do { \
if (sizeof("" __VA_ARGS__) > 1) \
complain(DBG_FATL_ABT, file ":" #line ": " __VA_ARGS__); \
- if (sizeof("" __VA_ARGS__) > 1) \
- ha_backtrace_to_stderr(1); \
abort_with_line(__LINE__); \
} while (0)
}; \
HA_WEAK(__start_dbg_cnt); \
HA_WEAK(__stop_dbg_cnt); \
- if (!_HA_ATOMIC_FETCH_ADD(&__dbg_cnt_##_line.count, 1) || _type != DBG_BUG_ONCE) { \
- complain_with_dbg(&__dbg_cnt_##_line); \
- if (_details & (DBG_DET_FAT_FATL|DBG_DET_FAT_WARN)) \
- ha_backtrace_to_stderr(!!(_details & DBG_DET_FAT_FATL)); \
- if (_details & DBG_DET_FAT_FATL) \
- abort_with_line(__LINE__); \
- } \
+ complain_with_dbg(&__dbg_cnt_##_line); \
+ if (_details & DBG_DET_FAT_FATL) \
+ abort_with_line(__LINE__); \
}
/* Matrix for DEBUG_COUNTERS:
({ static int __match_count_##line; \
!_HA_ATOMIC_FETCH_ADD(&__match_count_##line, 1); })) { \
complain(details, msg); \
- if (details & (DBG_DET_FAT_FATL|DBG_DET_FAT_WARN)) \
- ha_backtrace_to_stderr(!!(details & DBG_DET_FAT_FATL)); \
if (details & DBG_DET_FAT_FATL) \
abort_with_line(__LINE__); \
} \
void complain(uint details, const char *msg)
{
_complain(details, msg, NULL);
+
+ /* we may have to emit a backtrace on FATL/WARN.
+ * This must be the last statement for a tail jump.
+ */
+ if (details & (DBG_DET_FAT_FATL|DBG_DET_FAT_WARN))
+ ha_backtrace_to_stderr(!!(details & DBG_DET_FAT_FATL));
}
/* the same, for use with a debug_count struct */
void complain_with_dbg(struct debug_count *dbg)
{
+ if (_HA_ATOMIC_FETCH_ADD(&dbg->count, 1) && dbg->type == DBG_BUG_ONCE)
+ return;
_complain(dbg->details, NULL, dbg);
+
+ /* we may have to emit a backtrace on FATL/WARN.
+ * This must be the last statement for a tail jump.
+ */
+ if (dbg->details & (DBG_DET_FAT_FATL|DBG_DET_FAT_WARN))
+ ha_backtrace_to_stderr(!!(dbg->details & DBG_DET_FAT_FATL));
}
/* parse a "debug dev exit" command. It always returns 1, though it should never return. */