about summary refs log tree commit homepage
path: root/ext/mwrap/mwrap.c
DateCommit message (Collapse)
2023-01-13fix uninitialized .dump_csv for Mwrap.dump
.dump_csv was added to dump_args for the destructor, but not initialized properly for the Mwrap.dump API call.
2023-01-08drop dlsym use for rb_stderr
A weak symbol works fine, here.
2023-01-08Merge changes from the Perl side
This contains many changes from https://80x24.org/mwrap-perl.git commit * Built-in RCU-friendly version of dlmalloc, no more fragile dlsym(3m) resolution of malloc-family functions in the constructor * Allocations are now backed by O_TMPFILE on $TMPDIR on modern Linux. Since mwrap increases memory usage greatly and I needed to use it on a system where I needed more VM space but lacked the ability to add swap. * Configurable C backtrace level via MWRAP=bt:$DEPTH where $DEPTH is a non-negative integer. Be careful about increasing it, even a depth of 3-4 can be orders-of-magnitude more expensive in time and space. This can be changed dynamically at runtime via local HTTP (see below). * Embedded per-process local-socket-only HTTP server obsoletes MwrapRack when combined with mwrap-rproxy from the Perl dist (set `MWRAP=socket_dir:/dir/of/sockets') See https://80x24.org/mwrap-perl/20221210015518.272576-4-e@80x24.org/ for more info. It now supports downloading CSV (suitable for importing into sqlite 3.32.0+) * License switched to GPL-3+ to be compatible with GNU binutils since we may take code from addr2line in the future. * libxxhash supported if XXH3_64bits is available.
2023-01-07undefine Mwrap::SourceLocation.allocate
This quiets `undefining the allocator of T_DATA class Mwrap::SourceLocation' warnings.
2023-01-07drop heap page support for Ruby <= 3.0
Ruby 3.1 uses mmap, nowadays, and I don't think it's worth the effort to suport it since mmap and munmap don't require the symmetry *memalign + free do.
2022-09-03paranoid safety fix to clamp pathnames to PATH_MAX
While I doubt Ruby (nor Perl) would store pathnames longer than PATH_MAX by default, it's possible `eval' users to specify whatever path (and line number) they wish to use. Likely was the case with `# line $FILE' directives in Perl5 which prompted this clamping.
2022-09-03Ractor compatibility
We can no longer depend on having GVL/GIL when we have a Ruby execution context, so so make `kbuf' thread-specific to avoid data corruption. This was ported from the Perl5 version, since Perl5 has had MVM/Ractor-like abilities with native threads for decades, despite the Perl5 ecosystem largely avoids and discourages threads.
2022-09-03cleanup some FreeBSD-related workarounds
While FreeBSD 12.3 + Ruby 3.0.4p208 remains broken with mwrap (likely due to threading bugs in Ruby) at least get the code more consistently closer to a working state. Thus we'll remember to account for PTHREAD_MUTEX_INITIALIZER requiring malloc for HeapPageBody tracking, as we do with other mutexes. For reference, the Perl5 port of mwrap seems to have no problems on FreeBSD 12.3, so it seems down to misbehavior w.r.t. pthreads usage within Ruby itself. Perl5 on FreeBSD is configured with threads support, but Perl5 doesn't spawn background threads by default like Ruby can.
2022-08-23support --enabled-shared builds of Ruby
Most GNU/Linux distros build Ruby with --enable-shared, so it makes sense to support it properly even if it's not the default favored by ruby-core. __attribute__((weak)) on a local function is not weak enough for the shared library, so we add the extra check for the function's existence to have_ec_p(), instead. Tested with ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x86_64-linux-gnu] on Debian 11 (bullseye) as well as default builds w/o --enable-shared. Note: FreeBSD 12.3 appears broken with mwrap and I no longer have older FreeBSD systems handy.
2022-08-22various doc updates
Copyright years are unnecessary churn and probably aren't necessary: https://www.linuxfoundation.org/blog/copyright-notices-in-open-source-software-projects/ add POP3 and IMAP archive info, and drop the outdated link to the live demo since I no longer have the resources to run it. Finally, add rdoc (olddoc) + rsync support
2022-08-22quiet uninitialized and unused variable warnings
These warnings are already suppressed in similar ways in the Perl/XS port. The only warning which remains is related to cfree, which I'm leaving alone, for now, due to lack of use/test-cases: ../../../../ext/mwrap/mwrap.c:689:6: warning: ‘cfree’ specifies less restrictive attributes than its target ‘free’: ‘leaf’, ‘nothrow’ [-Wmissing-attributes] 689 | void cfree(void *) __attribute__((alias("free"))); | ^~~~~ /usr/include/stdlib.h:565:13: note: ‘cfree’ target declared here 565 | extern void free (void *__ptr) __THROW; | ^~~~
2022-08-22support Ruby 3.0.x
HEAP_PAGE_SIZE no longer estimates malloc overhead in Ruby 3.0.x, but we can now rely on the GC::INTERNAL_CONSTANTS hash to access the true value. We also need to account for Ractors in 3.0+, and thus we need to rely on thread-specific `ruby_current_ec' instead of process-wide `ruby_current_execution_context_ptr' (which no longer exists in 3.0+). Finally, the VM seems prone to making some small immortal allocations in a few places we were not expecting in 2.7 and earlier. Account for that and loosen some exact checks to account for it. Tested on Ruby 3.0.3 and 3.0.4
2022-08-22constify arg for totals_add_rcu
It's not modified by that function, so constify it for ease-of-reading and review.
2022-08-22workaround breakage from urcu v0.11.4
urcu v0.11.4+ introduced commit 7ca7fe9c03 (Make temporary variable in _rcu_dereference non-const, 2021-07-29) which conflicts with our use of _LGPL_SOURCE. In retrospect, CMM_LOAD_SHARED and CMM_STORE_SHARED seem sufficient for our use of the `totals' cds_lfht pointer since the constructur should always fire before any threads are running. This is fixed in urcu v0.12.4 and v0.13.2 (released 2022-08-18) but I suspect older versions will live on in enterprise/LTS distros for a long while. Link: https://lore.kernel.org/lttng-dev/20220809181927.GA3718@dcvr/
2022-08-09memalign: perform rcu_read_unlock on ENOMEM
We must not forget to release RCU read locks even if the process will probably die, soon, due to ENOMEM. I noticed this while working on the Perl5/XS port. Link: https://80x24.org/mwrap-perl/20191102020331.28050-4-e@80x24.org/
2019-10-31port to Perl5 and XS
I mainly use Perl5 (again :P), and sometimes tracking down where malloc calls happen is necessary. I don't know of any malloc wrapper interface which is aware of Perl source locations. Valgrind and similar tools can only figure out C source locations, which isn't very useful when hacking in Perl.
2018-08-11doc: 2.1 pre-release updates
Mwrap.total_bytes_allocated/total_bytes_freed API needs docs, and we need to clarify heap page stats are not reset.
2018-08-11struct acc: use 64-bit counters
Since there's no hope of atomicity here anyways, use 64-bit counters.
2018-08-11tweak hpb stats destructor output
Including the last rb_gc_count() call would be useful, and avoid showing giant SIZE_MAX initializers for acc.min fields.
2018-08-11struct acc: use 64-bit counters
Since there's no hope of atomicity here anyways, use 64-bit counters.
2018-08-11tweak hpb stats destructor output
Including the last rb_gc_count() call would be useful, and avoid showing giant SIZE_MAX initializers for acc.min fields.
2018-08-10allow dump_heap: mask via MWRAP env
This is useful for people who do not want to modify existing Ruby programs.
2018-08-10remove "memalign:" MWRAP option
Since we learned to treat heap_page_body allocations specially, we can also keep track of rare memalign allocations done outside of the Ruby GC this way.
2018-08-10keep stats for memalign-ed heap_page_body in Ruby
free-ing and calling posix_memalign again can cause fragmentation in glibc malloc (at least): https://sourceware.org/bugzilla/show_bug.cgi?id=14581 Add statistics to track lifetimes and deathtimes (time between free and resurrection via posix_memalign).
2018-07-26add global counters for total bytes allocated/freed
They can be accessed via new methods: Mwrap.total_bytes_allocated Mwrap.total_bytes_freed And reset (non-atomically) via Mwrap.reset Requested-by: Sam Saffron https://80x24.org/mwrap-public/CAAtdryPDZjXo0QWPznKgRnd7+jQPMBFBOQdfM31KWGUVgGPWeg@mail.gmail.com/
2018-07-20documentation updates for 2.0.0 release
2018-07-16support Mwrap.quiet to temporarily disable allocation tracking
Tracking memory used for monitoring code itself is noise, so give users the power to omit it.
2018-07-16disable memalign tracking by default
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.
2018-07-16do not track allocations for constructor and Init_
There's nothing a user can do about allocations which happen in our constructor (aside from not using mwrap), so do not track them.
2018-07-16use memrchr to extract address under glibc
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, ...)
2018-07-16fixes for FreeBSD 11.1...
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.
2018-07-16mwrap_aref: quiet -Wshorten-64-to-32 warning
An "int" length is enough for the source location length, as it's not going to exceed PATH_MAX by much.
2018-07-16implement accessors for SourceLocation
Knowing the average/max lifespan (in terms of GC.count) of allocations can be useful.
2018-07-16alias Mwrap.clear to Mwrap.reset
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.
2018-07-16allow analyzing live allocations via Mwrap[location]
This can be useful in apps to analyze what's live and what's not.
2018-07-16resolve real_malloc earlier for C++ programs
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++
2018-07-16reduce stack usage from file names
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.
2018-07-16memalign: check alignment on all public functions
And rework our internal_memalign interface to mimic the posix_memalign API; since that's what Ruby favors and avoids touching errno on errors.
2018-07-16ensure ENOMEM is preserved in errno when appropriate
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.
2018-07-16internal_memalign: do not assume real_malloc succeeds
Oops :x
2018-07-16realloc: do not copy if allocation failed
We shouldn't try to read NULL pointers :x
2018-07-16hold RCU read lock to insert each allocation
We need to hold the RCU read lock to ensure the liveness of the associated src_loc struct we'll be inserting into.
2018-07-16mwrap: use malloc to do our own memalign
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.
2018-07-16support per-allocation headers for per-alloc tracking
This increases costs even more, but will allow leak finding. It will be made optional in the future.
2018-07-15Mwrap.dump: do not segfault on invalid IO arg
Users may screw up ordering of arguments :x
2018-07-15use __attribute__((weak)) instead of dlsym
This should avoid indirect function call overhead as the symbol can be resolved at link time instead of at runtime with a constructor.
2018-07-02documentation updates
2018-07-02release GVL for most Ruby operations
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 :>
2018-07-02favor inline helpers instead of magic numbers
Hopefully this improves readability somewhat.
2018-07-02require Userspace RCU to track non-GVL allocations