我试图将websocketpp服务器集成到多线程项目中 . 在单线程方法中一切正常,但是在为后台运行的endpoint.listen()创建单独的boost :: thread时遇到了问题(因此它不会中断主线程的执行) . 我已经尝试使用Boost v1.46.1和v1.50.0在64位的Ubuntu 12.04上使用最新版本的websocketpp . 下面是代码示例和我的方法的解释 .
#include <websocketpp/websocketpp.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <exception>
using websocketpp::server;
class echo_server_handler : public server::handler {
public:
void on_message(connection_ptr con, message_ptr msg) {
con->send(msg->get_payload(),msg->get_opcode());
std::cout << "Got message: " << msg->get_payload() << std::endl;
}
};
int main(int argc, char* argv[]) {
unsigned short port = 9002;
try {
server::handler::ptr h(new echo_server_handler());
server echo_endpoint(h);
echo_endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
echo_endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
echo_endpoint.alog().set_level(websocketpp::log::alevel::CONNECT);
echo_endpoint.alog().set_level(websocketpp::log::alevel::DISCONNECT);
echo_endpoint.elog().set_level(websocketpp::log::elevel::RERROR);
echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);
std::cout << "Starting WebSocket echo server on port " << port << std::endl;
//Getting pointer to the right function
void(websocketpp::role::server<websocketpp::server>::*f)(uint16_t,size_t) =
&websocketpp::role::server<websocketpp::server>::listen;
std::cout << "Starting WSServer thread... \n" << std:endl;
boost::shared_ptr<boost::thread> ptr(new boost::thread(boost::bind(f, &echo_endpoint, port, 1)));
//ptr->join();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
//Simulating processing in the main thread
while(true) {std::cout << "Main thread processing..."<<std::endl; sleep(5);}
return 0;
}
如果我用ptr-> join()编译代码;监听线程工作正常,但它使主线程休眠 . 如果我离开ptr-> join()并让监听线程在后台运行,我在创建线程后遇到错误:
/usr/local/boost_1_50_0/libbin/include/boost/thread/pthread/recursive_mutex.hpp:105:void boost :: recursive_mutex :: lock():断言`!pthread_mutex_lock(&m)'失败 .
我对线程或增强线程不是很有经验,而且对于websocketpp也很新,所以我不确定我在这里做错了什么 . 如果有更好(和工作)的方法来解决这个问题,我很乐意看到一些例子 . 我一直试图找出这个问题很长一段时间,所以任何帮助都是无价的 . 提前致谢!
退房:gdb stacktrace和valgrind results
Edit: 代码示例中的"while(true)"只是为了模拟主线程中的处理 . 我真的会影响它们的创建顺序,因此必须在自己的线程中启动websocket服务器 .
2 回答
为什么在堆上创建
boost::thread
,它可能在堆栈上?您不需要将
boost::bind
与boost::thread
一起使用,因此它应该简单:更简单,不是吗?
至于你的程序的行为 . 如果你在那里调用
ptr->join()
那么主线程等待另一个线程完成,这从未发生过,所以当然它会睡觉 . 如果你没有加入它,那么ptr
和echo_endpoint
和h
都超出了范围 . 然后另一个线程将尝试使用不再存在的对象 .作为@IgorR . said,你应该把
while
循环放在try-catch块中,这样主循环中的工作就可以在另一个线程及其使用的对象超出范围之前发生 .从Boost 1.50开始,
boost::thread
析构函数匹配std::thread
的行为,即如果线程在其析构函数运行时可以连接,则它会调用terminate()
. 这是为了防止你所拥有的那种错误,即使引用它和其他堆栈对象的boost::thread
句柄不再存在,线程仍继续运行 . 如果你希望它继续运行你必须明确地显示它(但在你的程序中仍然是错误的,因为echo_endpoint
和h
对象仍然不复存在,并且线程仍然会尝试使用它们 . )所以在boost::thread
对象之前超出范围你应该join
它或detach
它 .您可以在try / catch范围内创建所有对象 . 离开此范围时,这些对象将被销毁 .
因此,要么将对象定义移出try / catch,要么将
while(true)
循环移入其中 .