PASSERT() - asserting for panics
John Baldwin
jhb at freebsd.org
Thu Sep 11 17:56:41 UTC 2008
On Wednesday 10 September 2008 08:06:57 pm Matthew Dillon wrote:
>
> :I think part of the pollution is that what I really want to do is treat a
> :panic like an exception that I can catch. I could probably make that idiom
> :work with two macros so your code can be:
> :
> : PANIC_TRY {
> : /* do stuff */
> : } PANIC_CATCH("foo");
> :
> :That could potentially work with some evil goto's that jumped between the
> :macros (i.e. have the setjmp() in PANIC_CATCH and PANIC_TRY goto's down to
> :--
> :John Baldwin
>
> Hmm. Almost java-like, where an exception pops back through subroutine
> levels until it finds a match. That kind of functionality would be a
> real mess in C. A limited form would be possible, something like this:
>
> #define PANIC_CATCH(label) \ (...)
> static jmpbuf label # _jmpbuf
> if (0) {
> for (;;) {
> longjmp(&label # _jmpbuf);
> label:
>
> #define PANIC_RETRY }}
>
> #define PANIC_PANIC panic(...); }}
>
> #define PASSERT(label, cond) \ (...)
> if (__predict_false(!(cond))) {
> setjmp (&label # _jmpbuf);
> goto label;
> }
>
> PANIC_CATCH(badthings) {
> ...
> PANIC_RETRY;
> }
>
> PANIC_CATCH(badthings) {
> ...
> PANIC_PANIC;
> }
>
> PASSERT(badthings, x == 1);
The problem is I want panics in unmodified code to be caught. For example, I
want to write regression tests to make sure assertions on locking primivities
fail when the state of the lock doesn't match what the assertion is
requiring. I can do something fairly simple though that lets me do this:
PANIC_TRY {
stuff;
} PANIC_CATCH {
IGNORE_PANIC("this one is ok");
/* WITNESS can do different panics in foo_assert() sometimes */
IGNORE_PANIC("this one is too");
UNEXPECTED_PANIC();
}
Without needing goto's.
> Which would allow you some control over the context plus allow multiple
> PASSERT's with the same label. But, OMG I don't know about doing
> setjmp/longjmp in the kernel. I don't think it would be worth it.
We use setjmp already if you get a trap in ddb so ddb doesn't crash.
> Theoretically one could cross procedural boundaries with the longjmp,
> and place the jmpbuf in a DATASET and have the kernel glue the longjmp
> address. That would be a candidate for the C obfuscation contest
> though.
To catch unmodified panics, I have to have the longjmp in panic() itself, and
I have the jmpbuf hung off of curthread.
--
John Baldwin
More information about the freebsd-arch
mailing list