Why my boost fiber code is deadlocking
Asked Answered
I

3

13

I've tried out boost::fibers::barrier and I cannot find out why the following code deadlocks:

#include <boost/fiber/all.hpp>
#include <iostream>
#include <boost/range/algorithm/generate.hpp>
#include <boost/range/algorithm/for_each.hpp>

void barrier_test()
{
    boost::fibers::barrier barrier(2);
    std::vector<boost::fibers::fiber> myfibers(4);
    boost::generate(myfibers, [&barrier]() {
        return boost::fibers::fiber([](boost::fibers::barrier& barrier) {
            static unsigned id_inc = 0;
            const auto id = ++id_inc;
            std::cout << "fiber id: " << boost::this_fiber::get_id() << " - local id: " << id << std::endl;
            barrier.wait();
            std::cout << "barrier passed, fiber id: " << boost::this_fiber::get_id() << " - local id: " << id << std::endl;
        }, std::ref(barrier) );
    });

    std::cout << "main fiber: " << boost::this_fiber::get_id() << std::endl;
    boost::for_each(myfibers, [](boost::fibers::fiber& aFiber) {
            aFiber.join();
    });
    std::cout << "end of program" << std::endl;
}

If I set the launch as "dispatch" it can go through. So it has something with the order of running, but I don't know what is wrong. So I've tried to imagine how locking goes behind the scene, what gets running, etc, but I just cannot find out, why the original code is not able to finish.

If somebody does not want to try it out, let me put here the output I see:

main fiber: 000000000042C960
fiber id: 000000000042C6E0 - local id: 1
fiber id: 000000000044CF60 - local id: 2
barrier passed, fiber id: 000000000044CF60 - local id: 2
fiber id: 000000000045D020 - local id: 3
fiber id: 000000000046D0E0 - local id: 4
barrier passed, fiber id: 000000000046D0E0 - local id: 4
barrier passed, fiber id: 000000000045D020 - local id: 3

I've copied a custom test scheduler algorithm of mine into the test code and I see, that after a while, no fiber is availabe for running, the local id 1 fiber is simply not continuing.

Boost version is 1.63 with visual studio 2015 precompiled package and the compilation is in 64bit

Intent answered 10/3, 2017 at 8:44 Comment(0)
L
1

I tried the program on Debian/unstable with boost-1.63.0 and I can confirm the problem. When I run the program using valgrind access to uninitialized memory is reported and later on also invalid reads, so I guess the problem is with that specific boost version.

Leckie answered 3/5, 2017 at 17:14 Comment(1)
Thanks, I did not try valgrind on this example, thanks for this confirmation.Intent
F
2

The code never deadlocks for me, but there are some variables to consider: I'm on a mac, I'm using boost 1.64, and I might have compiled boost differently.

boost? ./fibers 
main fiber: 0x7f877cc02bc0
fiber id: 0x100cbce00 - local id: 1
fiber id: 0x100ebce00 - local id: 2
barrier passed, fiber id: 0x100ebce00 - local id: 2
fiber id: 0x100fbce00 - local id: 3
fiber id: 0x1010bce00 - local id: 4
barrier passed, fiber id: 0x1010bce00 - local id: 4
barrier passed, fiber id: 0x100cbce00 - local id: 1
barrier passed, fiber id: 0x100fbce00 - local id: 3
end of program

FYI - I compiled and ran like this:

./bootstrap.sh --prefix=/Users/john/boost/boost_installation --without-libraries=python

./b2 install cxxflags='-std=c++14' -j 6 threading=multi variant=release link=shared stage --reconfigure

g++ -std=c++14 -I/Users/john/boost/boost_installation/include/ -L/Users/john/boost/boost_installation/lib -lboost_context -lboost_system -lboost_thread -lpthread -lboost_fiber -o fibers fibers.cpp

DYLD_LIBRARY_PATH=/Users/john/boost/boost_installation/lib

./fibers

This may not be what you need, but since it works for me I can't help you.

Francium answered 28/4, 2017 at 6:20 Comment(0)
L
1

I tried the program on Debian/unstable with boost-1.63.0 and I can confirm the problem. When I run the program using valgrind access to uninitialized memory is reported and later on also invalid reads, so I guess the problem is with that specific boost version.

Leckie answered 3/5, 2017 at 17:14 Comment(1)
Thanks, I did not try valgrind on this example, thanks for this confirmation.Intent
E
-1

change

boost::fibers::barrier barrier(2);

to

boost::fibers::barrier barrier(4);

or wait till boost-1.64 is released

Elimination answered 12/3, 2017 at 15:21 Comment(2)
This is not a solution, in this case you just extend the barrier to a bigger number and it will not hold up the fibers in pairs, but none. You wrote, that I should wait for boost-1.64, do you know about a bug in this by chance?Intent
I'm with @newhouse. Unless you know a logical reason to increase the barrier count, this is at best a cargo-culting answer. I'd give any programmer on my team a very stern talking to if they were to accept "magical advice" like this without any argumentation.Metallography

© 2022 - 2024 — McMap. All rights reserved.