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 | |
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')
-rw-r--r-- | src/libexpr/eval.cc | 31 | ||||
-rw-r--r-- | src/libexpr/local.mk | 2 |
2 files changed, 32 insertions, 1 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 diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index 687a8ccda..a5422169d 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -15,7 +15,7 @@ libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/lib libexpr_LIBS = libutil libstore libfetchers -libexpr_LDFLAGS = +libexpr_LDFLAGS = -lboost_context ifneq ($(OS), FreeBSD) libexpr_LDFLAGS += -ldl endif |