PASSERT() - asserting for panics

John Baldwin jhb at freebsd.org
Wed Sep 10 22:35:39 UTC 2008


On Wednesday 10 September 2008 05:26:59 pm Matthew Dillon wrote:
> :	PASSERT("foo", panic("foo"));
> :
> :The patch is at http://www.FreeBSD.org/~jhb/patches/passert.patch and 
below:
> :..
> 
>     The general problem with creating a more complex style of assertion
>     is, well, that it is more complex.  As a programmer who adds assertions
>     all over the place (HAMMER has 343 KKASSERTs, for example), the last
>     thing I want to do is to have to think about the assertion line itself
>     or have to read through the visual pollution.  Most of the time I just
>     want to KKASSERT(condition) and be done with it.
> 
>     I would consider using a DATASET (easily embedded in a statement as it
>     is a static declaration) to back the assertion macro and then simplify
>     it to just:
> 
> 	PASSERT(label, condition)
> 
>     The kernel would collect the DATASETs together and provide a sysctl
>     API to allow the action taken to be managed at run-time based on the
>     label.  You could even have a version that doesn't use a label at all
>     and is instead indexed by file and line.  The output would be the
>     stringtized condition (similar to libc's assert(cond) or DFly's
>     KKASSERT(cond)).  You could also have an optional macro to specify
>     a default action for the label, and a master global sysctl to override
>     everything.
> 
>     The actual code generated would simply be the conditional and, say,
>     a call to _passert(&dataset), reducing code pollution as well as visual
>     pollution.  I have considered doing something similar in DragonFly for
>     KKASSERT to reduce the code generated by the multi-argument panic()
>     it calls.

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:

	PASSERT_BEGIN("foo") {
		/* do stuff */
	} PASSERT_END;

It would be more like exceptions in C++ though to have the string at the end:

	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 
that and then CATCH goto's back to TRY when setjmp returns 0), but those 
would be gross.  The other problem is that you would probably be limited to a 
single TRY/CATCH per function, and I actually have some existing regression 
tests that do multiple potential panics in a single routine.

-- 
John Baldwin


More information about the freebsd-arch mailing list