The module handler code invokes a MOD_UNLOAD event immediately if
MOD_LOAD fails.  The result was that if seminit() failed, semunload()
was invoked twice.  semunload() is not idempotent however and would
try to remove it's process_exit eventhandler twice resulting in a
panic.
Details
- in a branch of CheriBSD we had a bug that caused seminit to fail which then exposed this as a boot-time panic
- we don't appear to have sysvsem tests in kyua directly, but I ran the sys/audit/interprocess tests which test audit record generation for sysvsem and those all passed
Diff Detail
- Lint
- Lint Passed 
- Unit
- No Test Coverage 
- Build Status
- Buildable 34021 - Build 31208: arc lint + arc unit 
Event Timeline
The behavior that MOD_UNLOAD gets invoked for a failed MOD_LOAD is perhaps surprising. Most of our other APIs aren't quite like that (e.g. we don't call device_detach() if device_attach() fails but instead require device_attach() to clean up if an error occurs).
Hm, seminit() fails if either sem_syscalls or sem32_syscalls registration fails.  In this case, there are a lot of resources allocated that needs to be freed.
On the other hand it seems that syscall_helper_register/unregister is not safe to do if register failed.  I believe this is what should be fixed somehow.
Yeah, I think this has tripped me up before. It might be nice to mention it in MODULE.9.
This does get cleaned up because of this code in module_register_init():
	MOD_SUNLOCK;
	error = MOD_EVENT(mod, MOD_LOAD);
	if (error) {
		MOD_EVENT(mod, MOD_UNLOAD);Also, syscall_helper_deregister() does DTRT since there is a per-syscall "is registered" flag.
The bug here is that it gets cleaned up twice, and semunload() can't be safely called twice.