'reorder_RR',
'option',
'env',
+ 'debugging',
'kres',
'libknot_SONAME',
'libzscanner_SONAME',
"modules\n modules configuration\n"
"kres\n resolver services\n"
"trust_anchors\n configure trust anchors\n"
+ "debugging\n debugging configuration\n"
;
lua_pushstring(L, help_str);
return 1;
void (*error)(struct kr_query *, const struct kr_transport *, enum kr_selection_error);
struct local_state *local_state;
};
+
kr_layer_t kr_layer_t_static;
+_Bool kr_dbg_assumption_abort;
+_Bool kr_dbg_assumption_fork;
+
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
const struct kr_query *qry);
struct kr_server_selection
EOF
-# a static variable; the line might not be simple to generate
-printf "kr_layer_t kr_layer_t_static;"
+# static variables; these lines might not be simple to generate
+printf "
+kr_layer_t kr_layer_t_static;
+_Bool kr_dbg_assumption_abort;
+_Bool kr_dbg_assumption_fork;
+"
printf "
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
__index = function (_, k) return os.getenv(k) end
})
+debugging = {}
+setmetatable(debugging, {
+ __index = function(_, k)
+ if k == 'assumption_abort' then return ffi.C.kr_dbg_assumption_abort
+ elseif k == 'assumption_fork' then return ffi.C.kr_dbg_assumption_fork
+ else panic('invalid debugging option: ' .. tostring(k))
+ end
+ end,
+ __newindex = function(_, k, v)
+ if k == 'assumption_abort' then ffi.C.kr_dbg_assumption_abort = v
+ elseif k == 'assumption_fork' then ffi.C.kr_dbg_assumption_fork = v
+ else panic('invalid debugging option: ' .. tostring(k))
+ end
+ end
+})
+
-- Quick access to interfaces
-- `net.<iface>` => `net.interfaces()[iface]`
-- `net = {addr1, ..}` => `net.listen(name, addr1)`
-- Make sandboxed environment
local function make_sandbox(defined)
- local __protected = { worker = true, env = true, modules = true, cache = true, net = true, trust_anchors = true }
+ local __protected = {
+ worker = true, env = true, debugging = true, modules = true,
+ cache = true, net = true, trust_anchors = true
+ }
-- Compute and export the list of top-level names (hidden otherwise)
local nl = ""
/* Logging & debugging */
bool kr_verbose_status = false;
-bool kr_debug_assumption = true;
+bool kr_dbg_assumption_abort = DBG_ASSUMPTION_ABORT;
+bool kr_dbg_assumption_fork = DBG_ASSUMPTION_FORK;
void kr_fail(bool is_fatal, const char *expr, const char *func, const char *file, int line)
{
else
kr_log_error("assumption \"%s\" failed in %s@%s:%d\n", expr, func, file, line);
- if (is_fatal || (kr_debug_assumption && fork() == 0))
+ if (is_fatal || (kr_dbg_assumption_abort && !kr_dbg_assumption_fork))
abort();
+ else if (kr_dbg_assumption_abort && kr_dbg_assumption_fork)
+ fork() == 0 ? abort() : (void)0;
}
/*
#define kr_assume(expression) kr_assume_func((expression), #expression, \
__func__, __FILE__, __LINE__)
-/** Whether kr_assume() checks should result fork and abort. */
-KR_EXPORT extern bool kr_debug_assumption;
+/** Whether kr_assume() checks should abort. */
+KR_EXPORT extern bool kr_dbg_assumption_abort;
+
+/** Whether kr_assume() should fork the process before issuing abort (if configured).
+ *
+ * This can be useful for debugging rare edge-cases in production. When both
+ * kr_debug_assumption_abort and kr_debug_assumption_fork are set to true, it is
+ * possible to both obtain a coredump (from forked child) and recover from the
+ * non-fatal error in the parent process. */
+KR_EXPORT extern bool kr_dbg_assumption_fork;
/** Use kr_require() and kr_assume() instead of directly this function. */
KR_EXPORT KR_COLD void kr_fail(bool is_fatal, const char* expr, const char *func,
conf_data.set('ENABLE_XDP', xdp.to_int())
conf_data.set('ENABLE_CAP_NG', capng.found().to_int())
conf_data.set('ENABLE_DOH2', nghttp2.found().to_int())
+conf_data.set('DBG_ASSUMPTION_ABORT', get_option('debug').to_int())
+conf_data.set('DBG_ASSUMPTION_FORK', (not get_option('debug')).to_int())
kresconfig = configure_file(
output: 'kresconfig.h',