|
Description
|
% cat a.c
int
main()
{
return (0);
}
% cc -o a a.c -lumem
% /usr/bin/mdb a
mdb: failed to read max_ncpus: unknown object file name
mdb: libumem.so.1 module failed to initialize
Loading modules: [ libc.so.1 ]
>
Here's the offending chunk of code:
#define UMEM_READVAR(var) \
(umem_readvar(&(var), #var) == -1 && \
((void) mdb_warn("failed to read "#var), 1))
int
umem_init(void)
{
size_t pagesize;
if (UMEM_READVAR(max_ncpus))
return (-1);
if (UMEM_READVAR(umem_stack_depth))
return (-1);
if (UMEM_READVAR(pagesize))
return (-1);
umem_pagesize = pagesize;
if (umem_stack_depth > UMEM_MAX_STACK_DEPTH) {
mdb_warn("umem_stack_depth corrupted (%d > %d)\n",
umem_stack_depth, UMEM_MAX_STACK_DEPTH);
umem_stack_depth = 0;
}
return (0);
}
Since the process hasn't been initialized yet, the vread fails.
----
Ooo. There's actually a bunch of problems here. The implementation above
was made to make an easy transition from the kernel. Unfortunately, when
the user process can change underneath, all kinds of problems start falling
out of the woodwork. This is one, but additionally, if you:
* stop process before first malloc() call.
* Load the umem module.
* run process past first malloc() call.
* Stop process
* Use umem dcmds.
The module will not function correctly -- umem_stack_depth and max_ncpus change
during initialization. To detect this, I think I'm going to want another
umem_init state (to cover the difference between all tunables fixed and all vmem
arenas/umem caches initialized). But I'll still be stuck calling a check
function at the top of _every_ dcmd and walk_init. Seems bad.
What would be nice is some way to register either:
1. a "program stopped" callback, or
2. a "first use of module since a program state change" callback.
Either would make it so that we're not filling the module with endlessly
repetitive code, and might come in handy for other state-caching situations
(i.e. ::findleaks)
---
As part of
6226887 kmdb should load dmods at boot
the kmem module was updated to use a state change callback (which was
added as part of kmdb). We can just use this, and re-read all of our
global variables from the state change handler.
|