- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
Boost 的 ASIO 调度器似乎有一个严重的问题,我似乎找不到解决方法。症状是唯一等待分派(dispatch)的线程留在 pthread_cond_wait
feven 尽管有 I/O 操作挂起需要它在 epoll_wait
中阻塞。
我可以通过让一个线程在循环中调用 poll_one
直到它返回零来最轻松地重现这个问题。这会使调用 run
的线程卡在 pthread_cond_wait
中,而调用 poll_one
的线程会跳出循环。据推测,io_service 期望该线程返回并在 epoll_wait
中阻塞,但它没有义务这样做,而且这种期望似乎是致命的。
是否要求线程与 io_service
静态关联?
这是一个显示死锁的示例。这是处理此 io_service 的唯一线程,因为其他线程已移动。肯定有套接字操作挂起:
#0 pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 boost::asio::detail::posix_event::wait<boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex> > (...) at /usr/include/boost/asio/detail/posix_event.hpp:80
#2 boost::asio::detail::task_io_service::do_run_one (...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:405
#3 boost::asio::detail::task_io_service::run (...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:146
我认为错误如下:如果为 I/O 队列提供服务的线程是阻塞在 I/O 套接字就绪检查上的线程,并且它调用调度函数,如果有任何其他线程阻塞在io服务,它必须发出信号。它目前仅在当时有准备运行的处理程序时发出信号。但是这样就没有线程检查套接字就绪情况。
最佳答案
这是一个错误。我已经能够通过在 task_io_service::do_poll_one
的非关键部分添加延迟来复制它。这是 booost/asio/detail/impl/task_io_service.ipp
中修改后的 task_io_service::do_poll_one()
的片段.唯一添加的行是 sleep 。
std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
task_io_service::thread_info& this_thread,
const boost::system::error_code& ec)
{
if (stopped_)
return 0;
operation* o = op_queue_.front();
if (o == &task_operation_)
{
op_queue_.pop();
lock.unlock();
{
task_cleanup c = { this, &lock, &this_thread };
(void)c;
// Run the task. May throw an exception. Only block if the operation
// queue is empty and we're not polling, otherwise we want to return
// as soon as possible.
task_->run(false, this_thread.private_op_queue);
boost::this_thread::sleep_for(boost::chrono::seconds(3));
}
o = op_queue_.front();
if (o == &task_operation_)
return 0;
}
...
我的测试驱动程序相当基础:
io_service
的线程。io_service
,并在轮询线程在 task_io_service::中休眠时进行主调用 io_service::run()
do_poll_one()
.测试代码:
#include <iostream>
#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
boost::asio::io_service io_service;
boost::asio::steady_timer timer(io_service);
void arm_timer()
{
std::cout << ".";
std::cout.flush();
timer.expires_from_now(boost::chrono::seconds(3));
timer.async_wait(boost::bind(&arm_timer));
}
int main()
{
// Add asynchronous work loop.
arm_timer();
// Spawn poll thread.
boost::thread poll_thread(
boost::bind(&boost::asio::io_service::poll, boost::ref(io_service)));
// Give time for poll thread service reactor.
boost::this_thread::sleep_for(boost::chrono::seconds(1));
io_service.run();
}
调试:
[twsansbury@localhost bug]$ gdb a.out ...(gdb) rStarting program: /home/twsansbury/dev/bug/a.out [Thread debugging using libthread_db enabled].[New Thread 0xb7feeb90 (LWP 31892)][Thread 0xb7feeb90 (LWP 31892) exited]
At this point, the arm_timer()
has printed "." once (when it was intially armed). The poll thread serviced the reactor in a non-blocking manner, and slept for 3 seconds while op_queue_
was empty (task_operation_
will be added back to the op_queue_
when task_cleanup c
exits scope). While the op_queue_
was empty, the main thread calls io_service::run()
, sees the op_queue_
is empty, and makes itself the first_idle_thread_
, where it waits on its wakeup_event
. The poll thread finishes sleeping, and returns 0
, leaving the main thread waiting on wakeup_event
.
After waiting 10~ seconds, plenty of time for the arm_timer()
to be ready, I interrupt the debugger:
Program received signal SIGINT, Interrupt.0x00919402 in __kernel_vsyscall ()(gdb) bt#0 0x00919402 in __kernel_vsyscall ()#1 0x0081bbc5 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0#2 0x00763b3d in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libc.so.6#3 0x08059dc2 in void boost::asio::detail::posix_event::wait >(boost::asio::detail::scoped_lock&) ()#4 0x0805a009 in boost::asio::detail::task_io_service::do_run_one(boost::asio::detail::scoped_lock&, boost::asio::detail::task_io_service_thread_info&, boost::system::error_code const&) ()#5 0x0805a11c in boost::asio::detail::task_io_service::run(boost::system::error_code&) ()#6 0x0805a1e2 in boost::asio::io_service::run() ()#7 0x0804db78 in main ()
The side-by-side timeline is as follows:
poll thread | main thread---------------------------------------+--------------------------------------- lock() | do_poll_one() | |-- pop task_operation_ from | | queue_op_ | |-- unlock() | lock() |-- create task_cleanup | do_run_one() |-- service reactor (non-block) | `-- queue_op_ is empty |-- ~task_cleanup() | |-- set thread as idle | |-- lock() | `-- unlock() | `-- queue_op_.push( | | task_operation_) | `-- task_operation_ is | queue_op_.front() | `-- return 0 | // still waiting on wakeup_event unlock() |
As best as I could tell, there are no side effects by patching:
if (o == &task_operation_)
return 0;
到:
if (o == &task_operation_)
{
if (!one_thread_)
wake_one_thread_and_unlock(lock);
return 0;
}
无论如何,我已经提交了 bug and fix .考虑密切关注工单以获得官方回复。
关于linux - 即使异步 I/O 操作挂起,也只有处理 io_service 的线程在等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15713832/
我有一个 ip::udp::socket用 io_service 构建.只有一个 boost::thread调用 io_service::run()方法,以及 io_service::work 的一个
我为异步 io_service 工作运行 aync 作业线程。 我想销毁用于异步作业的资源。 boost::asio::io_service boost::asio::io_service::work
我有一个 boost::asio 线程池,它有一个 asio::io_service和 asio::work : boost::asio::io_service m_service; boost::a
我正在编写多线程 TCP 服务器,基于应用程序设计,我需要有多个线程,每个线程都有 io_service。 通过该设计,我需要接受来自一个Thread/io_service 的连接,进行身份验证过程(
如果我io_service::run()只在一个线程中运行,那么io_service::post()调用是在我要求它们执行的顺序相同,或者它们可以按任意顺序执行,我仍然需要使用 strand 来强制序
boost::asio::io_service m_io_service; boost::asio::io_service::work m_work(m_io_service); m_io_servi
长话短说,我的代码: #include #include #include #include #include #include namespace ba = boost::asio; n
我的简化问题 我阅读了this thread,并试图删除io_service对象。我做这个 m_IO.stop(); m_IO.~io_service(); m_IO是boost::asio::io_
我使用 boost::asio::io_service 来处理 Foo 中的工作。现在它工作正常,直到我退出 ~Foo 并卡在 io_service 析构函数(在 service_registry 的
我想在里面的类中周期性地制作一个10秒的计时器,但是它不起作用。它会在 10 秒内第一次打印计数。但在那之后,它不会再等待 10 秒。具体代码。 #include #include #includ
我正在尝试运行 udp 服务器。问题是阻塞了 io_service 上的 run() 调用。所以我决定使用 boost bind 在其他线程上运行这个方法。结果主线程执行超出了 DictionaryI
我一直在阅读 boost asio 文档,特别是关于 Proactor 设计的。 当我看到这个标题的时候 前摄器设计模式:无线程的并发 我的理解是,asio 的用户不需要创建额外的线程来执行异步 IO
我想让程序等到它完成所有正在运行的线程,这与 ioService.stop(); 不同,后者无需等待即可停止 ioService。我尝试了以下代码,它工作正常,但没有等待线程完成就停止了 ioServ
为什么在这个简单的类中,如果我直接使用 io.run() 函数将被调用,否则如果要求运行到其他线程,打印将不会被调用? #include #include #include using name
正在尝试学习 asio,我正在关注网站上的示例。 为什么需要 io_service 以及它的具体作用是什么?为什么我在执行异步操作时需要将它发送到几乎所有其他函数,为什么它不能在第一次“绑定(bind
我正在使用boost::io_service构建并行执行计算作业的线程池。有些作业不允许同时运行,我认为这是boost::io_service::strand的理想应用。作为,执行顺序作业的顺序与无关
我正在编写一个网关服务,它监听网络套接字并将接收到的数据包路由到单独的守护进程。我打算使用 boost asio,但我遇到了几个问题。这是我计划实现的服务器的设计: 网关将使用 boost asio
我正在尝试实现一个包含两个处理循环的 C++ 应用程序。当前,第一个处理循环(boost 的 io_service::run)阻止了第二个处理循环的执行。 利用线程或 std::async 方法的方法
我正在尝试学习 io_service 并使用共享指针。我希望代码无限地工作,直到我像这样调用 stop 方法或某事。不幸的是,在屏幕上看到 workHandler 的输出后,程序关闭了。任何人都可以解
我更喜欢使用 io_service 的方式是在应用程序启动时创建一个线程来执行 io_service的运行方法。问题是,如果 io_service 没有任务,它的 run 方法立即返回并且线程终止。
我是一名优秀的程序员,十分优秀!