Date | Commit message (Collapse) |
|
This release includes significant changes to track live
allocations and frees. It can find memory leaks from malloc
with less overhead than valgrind's leakchecker and there is a
new Rack endpoint (MwrapRack) which can display live allocation
stats.
API additions:
* Mwrap#[] - https://80x24.org/mwrap/Mwrap.html#method-c-5B-5D
* Mwrap::SourceLocation - https://80x24.org/mwrap/Mwrap/SourceLocation.html
* MwrapRack - https://80x24.org/mwrap/MwrapRack.html
Incompatible changes:
* Mwrap.clear now an alias to Mwrap.reset; as it's unsafe
to implement the new Mwrap#[] API otherwise:
https://80x24.org/mwrap-public/20180716211933.5835-12-e@80x24.org/
26 changes since v1.0.0:
README: improve usage example
MANIFEST: add .document
add benchmark
use __attribute__((weak)) instead of dlsym
Mwrap.dump: do not segfault on invalid IO arg
bin/mwrap: support LISTEN_FDS env from systemd
support per-allocation headers for per-alloc tracking
mwrap: use malloc to do our own memalign
hold RCU read lock to insert each allocation
realloc: do not copy if allocation failed
internal_memalign: do not assume real_malloc succeeds
ensure ENOMEM is preserved in errno when appropriate
memalign: check alignment on all public functions
reduce stack usage from file names
resolve real_malloc earlier for C++ programs
allow analyzing live allocations via Mwrap[location]
alias Mwrap.clear to Mwrap.reset
implement accessors for SourceLocation
mwrap_aref: quiet -Wshorten-64-to-32 warning
fixes for FreeBSD 11.1...
use memrchr to extract address under glibc
do not track allocations for constructor and Init_
disable memalign tracking by default
support Mwrap.quiet to temporarily disable allocation tracking
mwrap_rack: Rack app to track live allocations
documentation updates for 2.0.0 release
|
|
|
|
Might as well be able to see and inspect what allocations
are alive when developing a Rack application.
Demo is available at https://80x24.org/MWRAP/each/2000 (note:
"MWRAP" is capitalized) This is also running "repobrowse",
which will eventually replace cgit on 80x24.org, but is NOT
running the main HTTPS termination at https://80x24.org/
Note: this demo machine is 32-bit, so yes, it will overflow
|
|
Tracking memory used for monitoring code itself is noise,
so give users the power to omit it.
|
|
Users will still pay the cost in memory overhead, but this
gets rid of misleading statistics. Tracking actual Ruby
object allocations is better left to Ruby itself.
|
|
There's nothing a user can do about allocations which happen
in our constructor (aside from not using mwrap), so do not
track them.
|
|
glibc will place the (virtual) address at the end, and this allows us to
find addresses for programs which put '[' in their progname (e.g. ssh,
mogilefsd, unicorn, avahi, ...)
|
|
PTHREAD_MUTEX_INITIALIZER is incomplete, in that it does lazy
initialization when pthread_mutex_init is called. So we call
pthread_mutex_init explicitly, as well as calling rcu_read_lock
during the constructor to initialize mutexes used by urcu-bp.
|
|
An "int" length is enough for the source location length, as
it's not going to exceed PATH_MAX by much.
|
|
Knowing the average/max lifespan (in terms of GC.count) of
allocations can be useful.
|
|
It is not safe to use the new Mwrap[] method with Mwrap.clear,
and the rcu_head overhead in src_loc structs was not worth it.
|
|
This can be useful in apps to analyze what's live and
what's not.
|
|
cmake (as run by the Ruby test suite for RubyGems) uses libjson
and libtasn1, which respectively call malloc (via `new') and
free before our constructor can even fire. Apparently, C++
variable initialization may call "new" outside of any functions;
and those run before any functions with the GCC constructor
attribute.
Disclaimer: I don't know C++
|
|
Ruby source locations can be extremely long and use excessive
stack space. Move it off stack for the temporary key lookup
to reduce the likelyhood of stack overflows. No need to use
TSD (which is stored on stack with GCC anyways); as we have
GVL at that point.
|
|
And rework our internal_memalign interface to mimic the
posix_memalign API; since that's what Ruby favors and
avoids touching errno on errors.
|
|
rcu_read_unlock may clobber errno, so it's our responsibility
to preserve it. Fortunately, ENOMEM is the only error which
real_malloc can fail with.
Also, do not set errno for posix_memalign.
|
|
Oops :x
|
|
We shouldn't try to read NULL pointers :x
|
|
We need to hold the RCU read lock to ensure the liveness
of the associated src_loc struct we'll be inserting into.
|
|
This reduces portability concerns about the various names of
memalign-related functions and should let us save some memory by
not requiring the malloc implementation to align-away the data.
|
|
This increases costs even more, but will allow leak finding.
It will be made optional in the future.
|
|
OK, Ruby blindly closing file descriptors it doesn't know about
is really getting on my nerves, now.
|
|
Users may screw up ordering of arguments :x
|
|
This should avoid indirect function call overhead as the
symbol can be resolved at link time instead of at runtime
with a constructor.
|
|
|
|
|
|
|
|
|
|
|
|
Most of this code is independent of Ruby. synchronize_rcu in
Mwrap#clear can take a while, and I would not rule out having a
version of this which works with Perl5 :>
|
|
And drop redundant versions in case people upgrade
by replacing a running process.
|
|
Hopefully this improves readability somewhat.
|
|
|
|
|