@john-lee
2021-01-03T02:40:15.000000Z
字数 5125
阅读 847
Boost.Asio
为了帮助调试异步程序,Boost.Asio 提供了对处理程序跟踪的支持。当通过定义BOOST_ASIO_ENABLE_HANDLER_TRACKING
,Boost.Asio 将调试输出写入标准错误流。输出记录异步操作及其处理程序之间的关系。
此功能在调试时很有用,您需要知道异步操作是如何链接在一起的,或者挂起的异步操作是什么。例如,以下是运行 HTTP Server 示例时输出,处理单个请求,然后通过 Ctrl+C 关闭:
@asio|1589424178.741850|0*1|signal_set@0x7ffee977d878.async_wait
@asio|1589424178.742593|0*2|socket@0x7ffee977d8a8.async_accept
@asio|1589424178.742619|.2|non_blocking_accept,ec=asio.system:11
@asio|1589424178.742625|0|resolver@0x7ffee977d760.cancel
@asio|1589424195.830382|.2|non_blocking_accept,ec=system:0
@asio|1589424195.830413|>2|ec=system:0
@asio|1589424195.830473|2*3|socket@0x7fa71d808230.async_receive
@asio|1589424195.830496|.3|non_blocking_recv,ec=system:0,bytes_transferred=151
@asio|1589424195.830503|2*4|socket@0x7ffee977d8a8.async_accept
@asio|1589424195.830507|.4|non_blocking_accept,ec=asio.system:11
@asio|1589424195.830510|<2|
@asio|1589424195.830529|>3|ec=system:0,bytes_transferred=151
@asio|1589424195.831143|3^5|in 'async_write' (./../../../boost/asio/impl/write.hpp:330)
@asio|1589424195.831143|3*5|socket@0x7fa71d808230.async_send
@asio|1589424195.831186|.5|non_blocking_send,ec=system:0,bytes_transferred=1090
@asio|1589424195.831194|<3|
@asio|1589424195.831218|>5|ec=system:0,bytes_transferred=1090
@asio|1589424195.831263|5|socket@0x7fa71d808230.close
@asio|1589424195.831298|<5|
@asio|1589424199.793770|>1|ec=system:0,signal_number=2
@asio|1589424199.793781|1|socket@0x7ffee977d8a8.close
@asio|1589424199.793809|<1|
@asio|1589424199.793840|>4|ec=asio.system:125
@asio|1589424199.793854|<4|
@asio|1589424199.793883|0|signal_set@0x7ffee977d878.cancel
每行都是以下形式:
<tag>|<timestamp>|<action>|<description>
<tag>
始终是@asio
,用于从程序输出中标识和提取跟踪消息的处理程序。
<timestamp>
是从UTC 1970年1月1日开始的秒和微秒。
<action>
采用以下形式之一:
n
。<description>
显示处理程序的参数。n
。n
。n
在未被调用的情况下被销毁。当io_context
被销毁时,任何未完成的异步操作通常都是这种情况。n
将创建一个新的异步操作,完成处理程序编号为m
。<description>
包含源位置信息,以帮助识别异步操作在程序中的何处启动。n
创建了一个新的异步操作,完成处理程序编号为m
。<description>
显示了启动的异步操作。n
执行了一些其它操作。<description>
显示调用了什么函数。当前只记录close()
和cancel()
操作,因为这些操作可能会影响挂起的异步操作的状态。n
是完成处理程序。<description>
显示调用了什么函数及其结果。这些跟踪事件仅在使用基于反应器的实现时发出。如果显示同步或异步操作,则格式为 <object-type>@<pointer>.<operation>
。对于处理程序条目,它显示参数及其值的逗号分隔列表。
如上所示,为每个处理程序分配一个数字标识符。如果处理程序跟踪输出显示处理程序编号为0,则表示该操作是在任何处理程序之外执行的。
程序可以通过在源代码中使用宏BOOST_ASIO_HANDLER_LOCATION
来扩充处理程序跟踪输出的位置信息。例如:
#define HANDLER_LOCATION \
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, __func__))
// ...
void do_read()
{
HANDLER_LOCATION;
auto self(shared_from_this());
socket_.async_read_some(boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
HANDLER_LOCATION;
if (!ec)
{
do_write(length);
}
});
}
利用可用的附加位置信息,处理程序跟踪输出可以包括源位置的调用栈:
@asio|1589423304.861944|>7|ec=system:0,bytes_transferred=5
@asio|1589423304.861952|7^8|in 'async_write' (./../../../boost/asio/impl/write.hpp:330)
@asio|1589423304.861952|7^8|called from 'do_write' (handler_tracking/async_tcp_echo_server.cpp:62)
@asio|1589423304.861952|7^8|called from 'operator()' (handler_tracking/async_tcp_echo_server.cpp:51)
@asio|1589423304.861952|7*8|socket@0x7ff61c008230.async_send
@asio|1589423304.861975|.8|non_blocking_send,ec=system:0,bytes_transferred=5
@asio|1589423304.861980|<7|
此外,如果std::source_location
或std::experimental::source_location
可用,则use_awaitable_t
令牌(当默认构造或用作默认完成令牌时)还将导致处理程序跟踪为每个新创建的异步操作输出源位置。还可以使用位置信息显式构造use_waitiable_t
对象。
处理程序跟踪输出可以使用包含的handlerviz.pl
工具来创建处理程序的可视化表示(需要GraphViz工具dot
)。
可以通过将BOOST_ASIO_CUSTOM_HANDLER_TRACKING
宏定义为头文件的名称(包含在""
或<>
)来定制处理跟踪。此头文件必须实现以下预处理器宏:
宏 | 描述 |
---|---|
BOOST_ASIO_INHERIT_TRACKED_HANDLER |
为实现异步操作的类指定基类。使用时,宏紧跟在类名之后,因此它必须具有以下形式:public my_class |
BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER |
为实现异步操作的类指定基类。使用时,宏跟随在其他基类之后,因此其形式必须为:public my_class |
BOOST_ASIO_HANDLER_TRACKING_INIT(args) |
用于初始化跟踪机制的表达式。 |
BOOST_ASIO_HANDLER_LOCATION(args) |
用于定义源代码位置的变量声明。args 是一个带圆括号的函数参数列表,包含文件名、行号和函数名。 |
BOOST_ASIO_HANDLER_CREATION(args) |
在创建异步操作时调用的表达式。args 是一个带圆括号的函数参数列表,其中包含所属的执行上下文、跟踪的处理程序、对象类型的名称、指向对象的指针、对象的本机句柄和操作名称。 |
BOOST_ASIO_HANDLER_COMPLETION(args) |
表达式的异步完成称为异步完成。args 是一个带圆括号的函数参数列表,其中包含跟踪的处理程序。 |
BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) |
在调用完成处理程序之前立即调用的表达式。args 是一个带圆括号的函数参数列表,其中包含完成处理程序的参数。 |
BOOST_ASIO_HANDLER_INVOCATION_END |
在调用完成处理程序后立即调用的表达式。 |
BOOST_ASIO_HANDLER_OPERATION(args) |
在调用某些同步对象操作(如close() 或cancel() )时调用的表达式。args 是一个带圆括号的函数参数列表,包含所属的执行上下文、对象类型的名称、指向对象的指针、对象的本机句柄和操作名称。 |
BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args) |
当对象注册到反应器时调用的表达式。args 是一个带圆括号的函数参数列表,包含所属的执行上下文、对象的本机句柄和唯一的注册KEY。 |
BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args) |
从反应器中注销对象时调用的表达式。args 是一个带圆括号的函数参数列表,包含所属的执行上下文、对象的本机句柄和唯一的注册KEY。 |
BOOST_ASIO_HANDLER_REACTOR_READ_EVENT |
用于标识反应器读准备就绪事件的位掩码常量。 |
BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT |
用于标识反应器写准备就绪事件的位掩码常量。 |
BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT |
用于标识反应器错误准备就绪事件的位掩码常量。 |
BOOST_ASIO_HANDLER_REACTOR_EVENTS(args) |
当注册到反应器的对象准备就绪时调用的表达式。args 是一个带圆括号的函数参数列表,包含所属的执行上下文、唯一的注册KEY和就绪事件的位掩码。 |
BOOST_ASIO_HANDLER_REACTOR_OPERATION(args) |
当实现作为基于反应器的异步操作的一部分执行系统调用时调用的表达式。args 是一个带圆括号的函数参数列表,包含跟踪的处理程序、操作名称、操作产生的错误代码和(可选)传输的字节数。 |
处理程序跟踪示例。
Copyright © 2003-2020 Christopher M. Kohlhoff
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)