diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-04-18 07:36:27 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-04-18 07:36:27 +0000 |
commit | 626bca37562b1a70eb657faa1c1827856fae85eb (patch) | |
tree | 6ee012b87c3e7f3ba3ec6e94e22ac7fa82f6ba29 | |
parent | 79fafa2bcce3f41fe044d3ebd86f071304bac36f (diff) | |
download | mailfromd-626bca37562b1a70eb657faa1c1827856fae85eb.tar.gz mailfromd-626bca37562b1a70eb657faa1c1827856fae85eb.tar.bz2 |
Sync with trunk
git-svn-id: file:///svnroot/mailfromd/branches/alpha_3_1_91_berkeley_txn@1364 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | NEWS | 25 | ||||
-rw-r--r-- | mflib/heloarg_test.mf | 4 | ||||
-rw-r--r-- | mflib/match_cidr.mf | 2 | ||||
-rw-r--r-- | mflib/match_dnsbl.mf | 4 | ||||
-rw-r--r-- | mflib/match_rhsbl.mf | 4 | ||||
-rw-r--r-- | mflib/spf.mf | 2 | ||||
-rw-r--r-- | mflib/valid_domain.mf | 2 | ||||
-rw-r--r-- | src/bi_other.m4 | 6 | ||||
-rw-r--r-- | src/gram.y | 6 | ||||
-rw-r--r-- | src/mailfromd.h | 1 | ||||
-rw-r--r-- | src/main.c | 16 | ||||
-rw-r--r-- | src/prog.c | 50 |
13 files changed, 119 insertions, 13 deletions
@@ -1,3 +1,13 @@ +2007-04-18 Sergey Poznyakoff <gray@gnu.org.ua> + + * src/gram.y (apply_deferred_init): Fix error messages + * src/mailfromd.h, src/prog.c, src/main.c, src/bi_other.m4, + NEWS: Implement stack traces. + + * mflib/match_dnsbl.mf, mflib/heloarg_test.mf, + mflib/valid_domain.mf, mflib/match_rhsbl.mf, mflib/spf.mf, + mflib/match_cidr.mf, doc/mailfromd.texi: Use <> in #include + 2007-04-17 Sergey Poznyakoff <gray@gnu.org.ua> * src/mu_dbm.c, src/mu_dbm.h: Use transactions for providing @@ -82,6 +82,31 @@ to the logs, notifying of the new stack size, e.g.: You can use these messages to adjust your stack size configuration settings. +* Runtime stack traces + +New command line option --stack-trace enables dumping stack traces +on runtime errors. This might help localize the source of the error. +The trace looks like: + +mailfromd: RUNTIME ERROR near ../mflib/match_cidr.mf:30: invalid CIDR (boo%) +mailfromd: Stack trace: +mailfromd: 0077: test.mf:7: match_cidr +mailfromd: 0096: test.mf:13: bar +mailfromd: 0110: test.mf:18: foo +mailfromd: Stack trace finishes +mailfromd: Execution of the configuration program was not finished + +Each trace line describes one stack frame, the lines appear in the +order of most recently called to least recently called. Each frame +consists of: + +1. Value of program counter at the time of its execution +2. Source code location, if available +3. Name of the function called + +The same output can be obtained by calling function stack_trace() +in your filter program. + * connect handler Connect handler is implemented. diff --git a/mflib/heloarg_test.mf b/mflib/heloarg_test.mf index 48587d39..840d38f0 100644 --- a/mflib/heloarg_test.mf +++ b/mflib/heloarg_test.mf @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include_once "is_ip.mf" -#include_once "dns.mf" +#include_once <is_ip.mf> +#include_once <dns.mf> const HELO_SUCCESS 0 const HELO_MYIP 1 # ARG is our IP address. diff --git a/mflib/match_cidr.mf b/mflib/match_cidr.mf index 92b7248a..e79b6586 100644 --- a/mflib/match_cidr.mf +++ b/mflib/match_cidr.mf @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include_once "status.mfh" +#include_once <status.mfh> #pragma regex push +extended diff --git a/mflib/match_dnsbl.mf b/mflib/match_dnsbl.mf index a361e156..585d6fe1 100644 --- a/mflib/match_dnsbl.mf +++ b/mflib/match_dnsbl.mf @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include_once "dns.mf" -#include_once "match_cidr.mf" +#include_once <dns.mf> +#include_once <match_cidr.mf> #pragma regex push +extended diff --git a/mflib/match_rhsbl.mf b/mflib/match_rhsbl.mf index 4bb855c9..f97e2bcc 100644 --- a/mflib/match_rhsbl.mf +++ b/mflib/match_rhsbl.mf @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include_once "dns.mf" -#include_once "match_cidr.mf" +#include_once <dns.mf> +#include_once <match_cidr.mf> #pragma regex push +extended func match_rhsbl(string email, string zone, string range) diff --git a/mflib/spf.mf b/mflib/spf.mf index 5a1c737e..eacaa5a6 100644 --- a/mflib/spf.mf +++ b/mflib/spf.mf @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include_once "safedb.mf" +#include_once <safedb.mf> #pragma regex push +extended +icase set spf_database "%__statedir__/spf.db" diff --git a/mflib/valid_domain.mf b/mflib/valid_domain.mf index bb49e924..d511e7eb 100644 --- a/mflib/valid_domain.mf +++ b/mflib/valid_domain.mf @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include_once "dns.mf" +#include_once <dns.mf> # boolean valid_domain (string DOMAIN) # diff --git a/src/bi_other.m4 b/src/bi_other.m4 index 5c7ed7d3..94e3e029 100644 --- a/src/bi_other.m4 +++ b/src/bi_other.m4 @@ -112,4 +112,10 @@ MF_DEFUN(cancel_program_trace, VOID, STRING name) } END +MF_DEFUN(stack_trace, VOID) +{ + runtime_stack_trace(env); +} +END + MF_INIT @@ -3470,13 +3470,13 @@ apply_deferred_init() for (p = deferred_decl; p; p = p->next) { struct variable *var = variable_lookup(p->name->text); if (!var) { - mu_error("<command line>: warning: no such variable %s", - p->name); + mu_error("<command line>: warning: no such variable: %s", + p->name->text); continue; } if (initialize_variable(var, &p->value, get_locus())) mu_error("error initialising variable %s: incompatible types", - p->name); + p->name->text); } } diff --git a/src/mailfromd.h b/src/mailfromd.h index c09f834b..23574182 100644 --- a/src/mailfromd.h +++ b/src/mailfromd.h @@ -275,6 +275,7 @@ extern int script_dump_xref; extern size_t lock_retry_count_option; extern time_t lock_retry_timeout_option; extern char *mailfromd_state_dir; +extern int stack_trace_option; /* Configuration file parser */ @@ -92,7 +92,7 @@ time_t lock_retry_timeout_option = 1; /* DBM-related options end */ int source_info_option; /* Debug messages include source locations */ - +int stack_trace_option; /* Print stack traces on runtime errors */ char *file_option; /* File name for DB management commands */ struct db_format *format_option; @@ -652,6 +652,12 @@ set_source_info(void *value) source_info_option = (int) value; } +void +set_stack_trace(void *value) +{ + stack_trace_option = (int) value; +} + static void set_lock_retry_count(void *value) { @@ -844,6 +850,7 @@ struct option_cache { { "ehlo", NULL, option_ehlo, set_ehlo }, { "debug", NULL, option_debug, set_debug }, { "source-info", NULL, option_boolean, set_source_info }, + { "stack-trace", NULL, option_boolean, set_stack_trace }, { "expire-interval", NULL, option_time, set_expire }, { "positive-expire-interval", NULL, option_time, set_positive_expire }, { "negative-expire-interval", NULL, option_time, set_negative_expire }, @@ -939,6 +946,7 @@ enum mailfromd_option { OPTION_PREDICT_NEXT, OPTION_SHOW_DEFAULTS, OPTION_SINGLE_PROCESS, + OPTION_STACK_TRACE, OPTION_SOURCE_INFO, OPTION_SYSLOG, OPTION_TIME_FORMAT, @@ -1085,6 +1093,8 @@ static struct argp_option options[] = { N_("Set the identifier used in syslog messages to STRING"), GRP+1 }, { "source-info", OPTION_SOURCE_INFO, NULL, 0, N_("Debug messages include source information"), GRP+1 }, + { "stack-trace", OPTION_STACK_TRACE, NULL, 0, + N_("Enable stack traces on runtime errors"), GRP+1 }, #undef GRP /*DEPRECATED OPTIONS*/ @@ -1347,6 +1357,10 @@ parse_opt (int key, char *arg, struct argp_state *state) single_process_option = 1; break; + case OPTION_STACK_TRACE: + set_option("stack-trace", "yes", 1); + break; + case OPTION_SOURCE_INFO: set_option("source-info", "yes", 1); break; @@ -358,6 +358,54 @@ prog_trace(eval_environ_t env, const char *fmt, ...) buf); } +void instr_funcall(eval_environ_t env); +void instr_locus(eval_environ_t env); + +void +runtime_stack_trace(eval_environ_t env) +{ + size_t base; + + mu_error("Stack trace:"); + for (base = env->base; base < datasize + env->stack_size - 4; + base = (size_t) env->dataseg[base + 1] + base + 1) { + int i; + prog_counter_t pc = (prog_counter_t)env->dataseg[base + 2] - 1; + char *name; + struct locus *ploc = NULL, loc; + + if (prog[pc-2] == instr_funcall) { + name = (char*)(env->dataseg + (size_t) prog[pc-1]); + pc -= 2; + } else { + name = "(in catch)"; + pc -= 3; + } + + for (i = 0; i < 10; i++) { + if (pc > i + 3 + && prog[pc - i - 3] == instr_locus) { + loc.file = (char*)(env->dataseg + + (size_t) prog[pc - i - 2]); + loc.line = (size_t) prog[pc - i - 1]; + ploc = &loc; + break; + } + } + + if (ploc) + mu_error("%04d: %s:%lu: %s", + (unsigned long) pc, + ploc->file, (unsigned long) ploc->line, + name); + else + mu_error("%04d: %s", + (unsigned long) pc, + name); + } + mu_error("Stack trace finishes"); +} + void runtime_warning(eval_environ_t env, const char *fmt, ...) { @@ -386,6 +434,8 @@ runtime_error(eval_environ_t env, const char *fmt, ...) vsnprintf(buf + n, sizeof buf - n, fmt, ap); va_end(ap); mu_error(buf); + if (stack_trace_option) + runtime_stack_trace(env); env->status = SMFIS_TEMPFAIL; /* FIXME */ longjmp(env->x_jmp, 1); } |