aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/serialise.cc
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2020-10-30 20:55:53 +0100
committerRobert Hensing <robert@roberthensing.nl>2020-10-30 21:21:59 +0100
commitc4d903ddb009aa6472530699e154d85a24eac51d (patch)
tree684cdcab5dffc917082d5f997010babebb8e2706 /src/libutil/serialise.cc
parentdc5696b84f55a6706cddc3d747ef1aeffb564f43 (diff)
Fix memory corruption caused by GC-invisible coroutine stacks
Crucially this introduces BoehmGCStackAllocator, but it also adds a bunch of wiring to avoid making libutil depend on bdw-gc. Part of the solutions for #4178, #4200
Diffstat (limited to 'src/libutil/serialise.cc')
-rw-r--r--src/libutil/serialise.cc35
1 files changed, 34 insertions, 1 deletions
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index 5c9f6f901..28f6968d0 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -171,6 +171,39 @@ size_t StringSource::read(unsigned char * data, size_t len)
#error Coroutines are broken in this version of Boost!
#endif
+/* A concrete datatype allow virtual dispatch of stack allocation methods. */
+struct VirtualStackAllocator {
+ StackAllocator *allocator = StackAllocator::defaultAllocator;
+
+ boost::context::stack_context allocate() {
+ return allocator->allocate();
+ }
+
+ void deallocate(boost::context::stack_context sctx) {
+ allocator->deallocate(sctx);
+ }
+};
+
+
+/* This class reifies the default boost coroutine stack allocation strategy with
+ a virtual interface. */
+class DefaultStackAllocator : public StackAllocator {
+ boost::coroutines2::default_stack stack;
+
+ boost::context::stack_context allocate() {
+ return stack.allocate();
+ }
+
+ void deallocate(boost::context::stack_context sctx) {
+ deallocate(sctx);
+ }
+};
+
+static DefaultStackAllocator defaultAllocatorSingleton;
+
+StackAllocator *StackAllocator::defaultAllocator = &defaultAllocatorSingleton;
+
+
std::unique_ptr<Source> sinkToSource(
std::function<void(Sink &)> fun,
std::function<void()> eof)
@@ -195,7 +228,7 @@ std::unique_ptr<Source> sinkToSource(
size_t read(unsigned char * data, size_t len) override
{
if (!coro)
- coro = coro_t::pull_type([&](coro_t::push_type & yield) {
+ coro = coro_t::pull_type(VirtualStackAllocator{}, [&](coro_t::push_type & yield) {
LambdaSink sink([&](const unsigned char * data, size_t len) {
if (len) yield(std::string((const char *) data, len));
});