Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deadlock when the input event port is disconnected from the output when the connection is active #334

Open
pdima opened this issue Sep 5, 2022 · 0 comments

Comments

@pdima
Copy link
Contributor

pdima commented Sep 5, 2022

The deadlock is caused by the different order of mutex locks during
inputPort->disconnect(outputPort); // input port mutex locked, output port mutex locked
and
outputPort->write(pkt); // output port mutex locked, input port mutex locked.

The bug can be reproduced in the toolchain-2.10 branch, example to reproduce the issue:

#include <gtest/gtest.h>
#include <thread>

#include <rtt/TaskContext.hpp>
#include <rtt/Activity.hpp>
#include <rtt/extras/SequentialActivity.hpp>
#include <rtt/OutputPort.hpp>
#include <rtt/InputPort.hpp>

namespace {
struct TestComponentWithOutputPort : public RTT::TaskContext
{
    TestComponentWithOutputPort(const std::string& name)
            : RTT::TaskContext(name)
    {
        addPort("output_port", port);
    }

    void updateHook()
    {
        port.write(42);
    }

    RTT::OutputPort<int> port;
};


struct TestComponentWithInputPort : public RTT::TaskContext
{
    TestComponentWithInputPort(const std::string& name)
            : RTT::TaskContext(name)
    {
        addEventPort("input_port", port, [&](RTT::base::PortInterface*) {
            port.read(value);
        });
    }

    void updateHook()
    {
    }

    RTT::InputPort<int> port;
    int value {0};
};
}

TEST(TestPortConnection, test_reconnect_ports)
{
//    std::thread t([&](){ // workaround for setActivity failed from the main thread
        TestComponentWithOutputPort task1("task1");
        task1.setActivity(new RTT::Activity(ORO_SCHED_OTHER,50, 0.001));

        TestComponentWithInputPort task2("task2");
        task2.setActivity(new RTT::extras::SequentialActivity());

        task1.configure();
        task2.configure();

        task1.start();
        task2.start();

        for (int i=0; i<10000; i++)
        {
            task2.port.connectTo(&task1.port);
//            task2.disconnect();  // deadlock
            task2.port.disconnect(&task1.port); // deadlock
//            task1.port.disconnect(&task2.port); // no deadlock
        }

        task2.stop();
        task1.stop();
//
//    });
//    t.join();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant