cpprestsdk同时使用boost.asio,acceptor就一直报Invalid argument。
本文目录,首先总结问题,然后案例还原。
总结:
问题的根本在于boost.asio作为header-only库,运行程序与动态库之间容易因为版本错配而产生运行期莫名其妙的问题。
cpprestsdk使用boost-1.53编译了动态库,运行程序通过cmake找库boost-1.53,但同时cmake_module_path包含了boost-1.7x的cmake帮助模块,致使程序实际却使用了boost-1.7x包含目录的配置,boost-1.53的库目录配置。
由于boost.asio是header-only库,cpprestsdk.so按boost-1.53方式访问io_service,并编译进库;运行程序却按boost-1.7x方式访问io_service。
由于程序整体(包括cpprestsdk.so)使用到的boost.asio的函数接口,两个版本的boost.asio并没有不一致,所以编译没有发生问题。但是io_service的结构却不同,编译没有发生问题,却不会被人发现。因此在运行期间,程序按boost-1.7x的结构定义创建io_service,cpprestsdk却按boost-1.53的结构定义访问。如果是发生了SIGSEGV一类内存访问越界,还容易发现,但却没有触发,只是变量在内存布局位置不同,而问题转移到其它函数,这些函数因为依赖io_service的变量而因为访问不到正确的值,触发参数错误。
正是因为上述原因,cpprestsdk不能正确读出io_service的epoll_fd_,从而编译在cpprestsdk.so的部分boost.asio代码在操作epoll时失败,也就是将22号errno抛出异常std::invalid_argument。
案例:
不要去企图调试pplx。
场境,cpprestsdk中的pplx只是ppl的一个修剪版,功力只有几成,而且没有timer,timer是另一个名为Asynchronous Agents Lib的类。所以只能使用boost.asio提供的timer。但是一旦代码加入了boost.asio的timer,http_listen.open().wait()就永远地抛“open: Invalid argument”。本例的平台环境是 10cores centos7。
调试开始:
线程抛异常。
一共有42个线程。
由http_listener.open().wait()抛出异常的backtrace。
不要去调试pplx,企图单步进去分析。open()异步到thread_pool,wait()阻塞等待task<>结果,然后将错误抛出异常。
也不要去调试cpprestsdk,你会接受一系列task的洗礼,无功而返。
根据异常信息分析,类型是boost::system::system_error,也就是系统调用,open函数报参数错误?socket是用socket()而不是open()。
断socket()分析。
上两图,主线程,正在wait;线程41正执行open的任务操作。线程41是什么?
线程41是由boost.asio库的threadpool创建的线程,运行io_service::run()的。为什么有40个线程,每个core创建了4个线程。
最后出现了我们的关键字“listener"。
可惜的是,socket()并没有失败,成功创建了fd:6的socket。
然后一波跟踪后,发现eventpoll的文件描述符有问题。
fd: 1是我们熟知的stdout,故一定出错。是谁手欠去将 epoll_fd_改掉了。只好在下次启动时,断epoll_create,找到epoll_fd_地址进行监视。但是让人崩溃的是,监视这个epoll_fd_,程序却直奔抛异常。
在几乎断线索的情况下,反过来一想epoll_fd_为什么就没有被访问呢,也就是说,我断的epoll_fd_,不是执行代码看到epoll_fd_,原因只有一个可能,我俩眼里的 io_service西施压根不是同一时空的。一查CMakeFiles里的CXX_includes发现,我的程序原来在使用boost-1.7x,我编译的cpprestsdk在使用boost-1.53,尽管我强调了find_package(Boost 1.53 REQUIRED),无奈CMAKE_MODULE_PATH包含了boost-1.7的帮助cmake却不知道。
事实上,这个错误浪费了不止上面贴出的过程的时间。因为在开始没有头绪的时候,还要先排除boost::asio timer对cpprestsdk.so的影响,毕竟是加了它才出问题。还有痛苦的pplx异步任务跟踪,徒劳无功。上面的案例是归纳修正思路后,案例重演调试,也就是几步,因为我以经知道问题所在,方向还怎么走到清楚。实际上就一yuan大头,浪费了多少时间。
cpprestsdk同时使用boost.asio,acceptor就一直报Invalid argument。的更多相关文章
- boost asio acceptor 构造
boost::asio::io_service io_svc; boost::asio::ip::address_v4 lis_ip; // 默认监听本机所有IP boost::asio::ip::t ...
- BOOST.Asio——Tutorial
=================================版权声明================================= 版权声明:原创文章 谢绝转载 啥说的,鄙视那些无视版权随 ...
- Boost.Asio的使用技巧
基本概念 Asio proactor I/O服务 work类 run() vs poll() stop() post() vs dispatch() buffer类 缓冲区管理 I/O对象 socke ...
- (原创)如何使用boost.asio写一个简单的通信程序(一)
boost.asio相信很多人听说过,作为一个跨平台的通信库,它的性能是很出色的,然而它却谈不上好用,里面有很多地方稍不注意就会出错,要正确的用好asio还是需要花一番精力去学习和实践的,本文将通过介 ...
- 01--c实现基础客户端和服务端与c++ boost.asio实现对比
c实现服务端和客户端交互: 学习查阅的博客: https://blog.csdn.net/u011068702/article/details/54380259 https://blog.csdn.n ...
- c++ boost asio库初学习
前些日子研究了一个c++的一个socket库,留下范例代码给以后自己参考. 同步server: // asio_server.cpp : コンソール アプリケーションのエントリ ポイントを定義します. ...
- 如何在多线程leader-follower模式下正确的使用boost::asio。
#include <assert.h> #include <signal.h> #include <unistd.h> #include <iostream& ...
- BOOST.Asio——Overview
=================================版权声明================================= 版权声明:原创文章 谢绝转载 啥说的,鄙视那些无视版权随 ...
- boost asio sync
Service: #include<boost/asio.hpp> #include<boost/thread.hpp> #include<iostream> #i ...
随机推荐
- Blazor入门:ASP.NET Core Razor 组件
目录 关于组件 组件类 静态资产 路由与路由参数 组件参数 请勿创建会写入其自己的组参数属性的组件 子内容 属性展开 任意参数 捕获对组件的引用 在外部调用组件方法以更新状态 使用 @ 键控制是否保留 ...
- 【Hadoop离线基础总结】完全分布式环境搭建
完全分布式环境搭建 服务规划 适用于工作当中正式环境搭建 安装步骤 第一步:安装包解压 停止之前的Hadoop集群的所有服务,并删除所有机器的Hadoop安装包,然后重新解压Hadoop压缩包 三台机 ...
- Spring JDBC 框架使用JdbcTemplate 类的一个实例
JDBC 框架概述 在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等.但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQ ...
- PHP导出excel文件之权限字段筛选导出
因为导出excel时要过滤掉不是自身权限内的数据,权限有专门的字段,所以导出的数据要具体考量,数据库权限字段是MMId,因为登录的时候MMId已存入SESSION,所以导出的时候只要判断是否在此SES ...
- Qt5.5 connection firebird on Linux Centos7.2 or windows
windows c++ 项目移植到 linux,原项目需要连接 Firebird数据库. google 后知道 linux qt connection Firebird 有两种方法: 1.ibpp c ...
- Python --函数学习2
一.函数参数和返回值 --参数:负责给函数传递一些必要的数据或者信息 -形参(形式参数):在函数定义的时候用到的参数,没有具体值,只是一个占位符号 -实参(实际参数):在调用函数的时候输入的值 exa ...
- DVWA-反射型XSS
0x01 XSS介绍 XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器 ...
- java-> 利用IO操作与递归实现目录的复制
public class CopyDir { public static void main(String[] args) { copyDir(new File("d:\\a"), ...
- 原生js获取元素的各种位置(大全)
加给元素: offsetLeft (距离定位父级的距离) offsetTop (距离定位父级的距离) offsetWidth (可视宽度) offsetHeight (可视高度) clientLeft ...
- Puppeteer笔记(一):Puppeteer简介
一.Puppeteer简介 Puppeteer是NPM库,它提供了NodeJS高级API来控制Chrome.Puppeteer 默认以无头(无界面)方式运行,但也可以配置为运行有界面的Chrome. ...