diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2020-11-05 10:18:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-05 10:18:31 +0100 |
commit | 387f824cab50682e373ade49dcec4e6f99c10a42 (patch) | |
tree | 01b25bfb61801cc79096b6a71201182a2dc92ab4 /src/libexpr/eval.cc | |
parent | 5e6eabe1551f3fa2a463fced39a4a48b504ed1ab (diff) | |
parent | b43c13a9161daf1801188e61104debafa5243fe1 (diff) |
Merge pull request #4206 from hercules-ci/fix-coroutine-gc
Fix memory corruption caused by GC-invisible coroutine stacks
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index cb8e0a0de..5e3fcf4ac 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -27,6 +27,10 @@ #include <gc/gc.h> #include <gc/gc_cpp.h> +#include <boost/coroutine2/coroutine.hpp> +#include <boost/coroutine2/protected_fixedsize_stack.hpp> +#include <boost/context/stack_context.hpp> + #endif namespace nix { @@ -220,6 +224,31 @@ static void * oomHandler(size_t requested) /* Convert this to a proper C++ exception. */ throw std::bad_alloc(); } + +class BoehmGCStackAllocator : public StackAllocator { + boost::coroutines2::protected_fixedsize_stack stack { + // We allocate 8 MB, the default max stack size on NixOS. + // A smaller stack might be quicker to allocate but reduces the stack + // depth available for source filter expressions etc. + std::max(boost::context::stack_traits::default_size(), static_cast<std::size_t>(8 * 1024 * 1024)) + }; + + public: + boost::context::stack_context allocate() override { + auto sctx = stack.allocate(); + GC_add_roots(static_cast<char *>(sctx.sp) - sctx.size, sctx.sp); + return sctx; + } + + void deallocate(boost::context::stack_context sctx) override { + GC_remove_roots(static_cast<char *>(sctx.sp) - sctx.size, sctx.sp); + stack.deallocate(sctx); + } + +}; + +static BoehmGCStackAllocator boehmGCStackAllocator; + #endif @@ -257,6 +286,8 @@ void initGC() GC_set_oom_fn(oomHandler); + StackAllocator::defaultAllocator = &boehmGCStackAllocator; + /* Set the initial heap size to something fairly big (25% of physical RAM, up to a maximum of 384 MiB) so that in most cases we don't need to garbage collect at all. (Collection has a |