Proposal: Unify printing the function name in panic messages()
John Baldwin
jhb at freebsd.org
Wed Feb 13 16:00:02 UTC 2013
On Monday, February 11, 2013 8:34:38 pm Kirk McKusick wrote:
> I have recently gone down several ratholes trying to understand a
> panic message which had the wrong function name (prefix ufs1_ instead
> of ufs2_). I can definitely say that it matters to me. And I think
> that fixing the problem as Christoph has outlined will be a big
> step in the right direction.
>
> John, in your code you cannot expect to match the entire panic
> string if it has any % formats in it. So to be useful, you must be
> able to work with a constant subset of the string. The addition of
> other information such as a function name at the start should not
> affect that constant part that you are trying to match.
Actually, that's not quite true. I store both the "raw" format string
and a generated string in an on-stack buffer in the PANIC_TRY macro
that is compared against. Some more examples:
static int
test_no_sleeping_recursion(void)
{
struct timespec before, after;
int error;
/* These tests will DROP_GIANT before panic'ing. */
DROP_GIANT();
THREAD_NO_SLEEPING();
PANIC_TRY {
tsleep(&test_wchan, 0, "sleep", 1);
} PANIC_CATCH {
sleepq_release(&test_wchan);
IGNORE_PANIC("%s: td %p to sleep on wchan %p with sleeping prohibited");
} PANIC_END;
THREAD_NO_SLEEPING();
PANIC_TRY {
tsleep(&test_wchan, 0, "sleep", 1);
} PANIC_CATCH {
sleepq_release(&test_wchan);
IGNORE_PANIC("%s: td %p to sleep on wchan %p with sleeping prohibited");
} PANIC_END;
THREAD_SLEEPING_OK();
PANIC_TRY {
tsleep(&test_wchan, 0, "sleep", 1);
} PANIC_CATCH {
sleepq_release(&test_wchan);
IGNORE_PANIC("%s: td %p to sleep on wchan %p with sleeping prohibited");
} PANIC_END;
THREAD_SLEEPING_OK();
nanouptime(&before);
error = tsleep(&test_wchan, 0, "sleep", hz);
nanouptime(&after);
KASSERT(error == EWOULDBLOCK, ("tsleep did not timeout: %d", error));
PICKUP_GIANT();
return (TEST_OK);
}
UNIT_TEST("sleeping disabled recursion", test_no_sleeping_recursion);
(This panic already use __func__ explicitly)
And my unit tests for PANIC_TRY itself:
static int
catch_panics(void)
{
PANIC_TRY {
panic("test");
} PANIC_CATCH {
IGNORE_PANIC("test");
} PANIC_END;
PANIC_TRY {
panic("test longer message");
} PANIC_CATCH {
IGNORE_PANIC_STARTS_WITH("test");
} PANIC_END;
PANIC_TRY {
panic("test %s", "raw message");
} PANIC_CATCH {
IGNORE_PANIC("test %s");
} PANIC_END;
PANIC_TRY {
panic("test %s", "formatted message");
} PANIC_CATCH {
IGNORE_PANIC("test formatted message");
} PANIC_END;
return (TEST_OK);
}
UNIT_TEST("catching panics", catch_panics);
static int
unexpected_panics(void)
{
PANIC_TRY {
PANIC_TRY {
panic("test");
} PANIC_CATCH {
} PANIC_END;
} PANIC_CATCH {
IGNORE_PANIC_STARTS_WITH("Unexpected panic");
} PANIC_END;
PANIC_TRY {
PANIC_TRY {
panic("foo");
} PANIC_CATCH {
IGNORE_PANIC("bar");
IGNORE_PANIC_STARTS_WITH("b");
} PANIC_END;
} PANIC_CATCH {
IGNORE_PANIC_STARTS_WITH("Unexpected panic");
} PANIC_END;
return (TEST_OK);
}
UNIT_TEST("unexpected panics", unexpected_panics);
TESTER_MODULE(panic);
If every panic has a slightly '%s:' at the front that is perhaps
less painful to deal with in the unformatted case. In the case
that you want a test to catch a formatted message then it's a bit
less obvious you need to prepend the relevant function name.
--
John Baldwin
More information about the freebsd-arch
mailing list