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

Jupyter Kernel Notebook Dies After Starting Threaded Class #893

Open
MasterBe opened this issue Apr 28, 2024 · 0 comments
Open

Jupyter Kernel Notebook Dies After Starting Threaded Class #893

MasterBe opened this issue Apr 28, 2024 · 0 comments

Comments

@MasterBe
Copy link

I am using Boost Python to expose a function that holds an internal thread, the class has start and stop functions that only control an internal loop. The code for MyClass is:

#include <iostream>
#include <atomic>
#include <thread>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/make_constructor.hpp>

class MyClass
{
private:
    std::atomic<bool> running_;
    std::thread worker_;
    std::function<std::string(std::string)> m_op;


    void printMessage()
    {
        std::string s = "hello";
        while (running_)
        {
            s = m_op(s);
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }

public:
    MyClass() : running_(false) {}
    MyClass(const std::function<std::string(std::string)>& op) : running_(false), m_op(op) {}

    void start()
    {
        if (!running_)
        {
            running_ = true;
            worker_ = std::thread(&MyClass::printMessage, this);
        }
    }

    void stop()
    {
        if (running_)
        {
            running_ = false;
            worker_.join();
        }
    }
};

I then create a helper function to pass a callback as:

template<class output_tp, class... input_tps>
struct function_helper
{
    function_helper(const boost::python::object& op) : m_op(op) {}

    output_tp operator()(input_tps&&... args)
    {
        return boost::python::call<output_tp>(m_op.ptr(), std::forward<input_tps>(args)...);
    }

private:
    boost::python::object m_op;
};

boost::shared_ptr<MyClass> makeMakeClass(const boost::python::object& obj)
{
    return boost::make_shared<MyClass>(function_helper<std::string, std::string>(obj));
}

I then create my module:

BOOST_PYTHON_MODULE(draft)
{
    using namespace boost::python;

    class_<MyClass, bases<>, boost::shared_ptr<MyClass>, boost::noncopyable>("MyClass")
        .def("__init__", make_constructor(makeMakeClass))
        .def("start", &MyClass::start)
        .def("stop", &MyClass::stop);
}

I use the draft module in jupyter as follows attached

jupyter

The first run causes a crash as in

kernel

The second run is not throwing but produces nothing. Could you please help me make this work.

UPDATE
I figured a partial source of the problem, this line boost::python::call is what is causing issues, wondering if it's a memory thing when copying const boost::python::object& op. Still stuck on how to make to the above work though.

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