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
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
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.