aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-11-05 10:18:31 +0100
committerGitHub <noreply@github.com>2020-11-05 10:18:31 +0100
commit387f824cab50682e373ade49dcec4e6f99c10a42 (patch)
tree01b25bfb61801cc79096b6a71201182a2dc92ab4 /src/libexpr
parent5e6eabe1551f3fa2a463fced39a4a48b504ed1ab (diff)
parentb43c13a9161daf1801188e61104debafa5243fe1 (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.cc31
-rw-r--r--src/libexpr/local.mk2
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