Рассмотрим следующее простое расширение python. Когда start()-ed
, Foo
будет просто добавить следующий последовательный целое в py::list
, один раз в секунду:Повышенная ошибка сегментации резьбы на python
#include <boost/python.hpp>
#include <thread>
#include <atomic>
namespace py = boost::python;
struct Foo {
Foo() : running(false) { }
~Foo() { stop(); }
void start() {
running = true;
thread = std::thread([this]{
while(running) {
std::cout << py::len(messages) << std::end;
messages.append(py::len(messages));
std::this_thread::sleep_for(std::chrono::seconds(1));
}
});
}
void stop() {
if (running) {
running = false;
thread.join();
}
}
std::thread thread;
py::list messages;
std::atomic<bool> running;
};
BOOST_PYTHON_MODULE(Foo)
{
PyEval_InitThreads();
py::class_<Foo, boost::noncopyable>("Foo",
py::init<>())
.def("start", &Foo::start)
.def("stop", &Foo::stop)
;
}
Учитывая вышеизложенное, следующий простой питон скрипт возвращает ошибку сегментации все время, никогда даже и не печатать ничего:
>>> import Foo
>>> f = Foo.Foo()
>>> f.start()
>>> Segmentation fault (core dumped)
с ядром, указывая на:
namespace boost { namespace python {
inline ssize_t len(object const& obj)
{
ssize_t result = PyObject_Length(obj.ptr());
if (PyErr_Occurred()) throw_error_already_set(); // <==
return result;
}
}} // namespace boost::python
Где:
(gdb) inspect obj
$1 = (const boost::python::api::object &) @0x62d368: {<boost::python::api::object_base> = {<boost::python::api::object_operators<boost::python::api::object>> = {<boost::python::def_visitor<boost::python::api::object>> = {<No data fields>}, <No data fields>}, m_ptr = []}, <No data fields>}
(gdb) inspect obj.ptr()
$2 = []
(gdb) inspect result
$3 = 0
Почему это происходит при запуске в потоке? obj
выглядит хорошо, result
устанавливается правильно. Почему происходит PyErr_Occurred()
? Кто это устанавливает?
* было бы обидно, если бы такой отличный ответ получил только один взлет * ... Больше нет! –