핸들러 추적 (Handler Tracking)
비동기식 프로그램의 디버깅을 지원하기 위해 Boost.Asio는 핸들러 추적 기능을 지원한다. BOOST_ASIO_ENABLE_HANDLER_TRACKING을 정의하여 기능이 활성화되면, Boost.Asio는 표준 오류 스트림(standard error stream)에 디버깅 출력을 기록한다. 출력은 비동기식 작업과 핸들러 간의 관계를 기록한다.
이 기능은 디버깅할 때, 비동기식 작업이 체인으로 연결된 방식이나 보류 중인(pending) 비동기식 작업이 무엇인지 알아야 하는 경우 유용하다. 다음은 HTTP 서버 예제를 실행하고 단일 요청을 처리한 후 "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>는 1970년 1월 1일 UTC의 초와 마이크로초 이다.
<action>는 다음 형식 중 하나를 가진다:
>n
프로그램에서 핸들러 번호 n을 입력했다. <description>는 핸들러에 대한 인수(arguments)를 보여준다.
<n
프로그램에서 핸들러 번호 n이 떠났다.
!n
프로그램에서 예외로 인해 핸들러 번호 n을 떠났다.
~n
핸들러 번호 n이 호출되지 않고 삭제되었다. 이는 일반적으로 io_context가 삭제될 때 완료되지 않은 비동기 작업의 경우이다.
n^m
핸들러 번호 n은 완료 핸들러 번호 m을 사용하여 새로운 비동기 작업을 생성하려고 한다. <description>에는 프로그램에서 비동기 작업이 시작되고 있는 위치를 식별하는 데 도움이 되는 소스 위치 정보가 포함되어 있다.
n*m
핸들러 번호 n은 완료 핸들러 번호 m을 사용하여 새로운 비동기 작업을 생성했다. <description>은 시작된 비동기 작업을 보여준다.
n
핸들러 번호 n이 다른 작업을 수행했다. <description>은 어떤 함수가 호출되었는지 보여준다. 현재는 close()와 cancel() 작업만 기록되는데, 이는 보류 중인(pending) 비동기 작업의 상태에 영향을 미칠 수 있다.
.n
구현은 핸들러 번호 n이 완료 핸들러인 비동기 작업의 일부로 시스템 호출을 수행했다. <description>은 호출된 함수와 결과를 보여준다. 이런 이벤트 추적은 reactor 기반 구현을 사용할 때만 발생한다.
<description>에 동기식이나 비동기식 작업이 표시되는 경우, 형식은 <object-type>@<pointer>. <operation>이다. 핸들러 항목의 경우, 인수와 인수 값의 목록을 쉼표로 구분해서 표시한다.
위와 같이, 각 핸들러에는 숫자 식별자가 할당된다. 핸들러 추적 출력에서 핸들러 번호 0이 표시된다면, 이는 작업이 핸들러 외부에서 수행되었음을 의미한다.
위치 정보 추가 (Adding Location Information)
프로그램은 소스 코드에서 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_awaitable_t 객체는 위치 정보를 명시적으로 구성할 수도 있다.
시각적 표현 (Visual Representations)
핸들러 추적 출력은 핸들러의 시각적 표현을 생성하기 위해 포함된 handlerviz.pl 도구를 사용하여 후처리(post-processed)할 수 있다(GraphViz tool dot 필요).
사용자 지정 추적 (Custom Tracking)
추적 처리는 BOOST_ASIO_CUSTOM_HANDLER_TRACKING 매크로를 헤더 파일 이름(""나 <>에 이름이 포함되는 파일)으로 정의하여 사용자 정의를 할 수 있다. 이 헤더 파일은 다음과 같은 전처리기 매크로(preprocessor macros)로 구현해야 한다:
매크로 | 설명 |
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) | Reactor에 개체가 등록될 때 호출되는 표현식이다. args는 소유한 실행 컨텍스트, 개체의 네이티브 핸들 및 고유한 등록 키를 포함하는 괄호로 묶인 함수 인수 목록이다. |
BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args) | Reactor에서 개체가 해지될 때 호출되는 표현식이다. args는 소유한 실행 컨텍스트, 개체의 네이티브 핸들 및 고유한 등록 키를 포함하는 괄호로 묶인 함수 인수 목록이다. |
BOOST_ASIO_HANDLER_REACTOR_READ_EVENT | Reactor로 읽기 준비 상태 이벤트 식별에 사용되는 비트마스트 상수. |
BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT | Reactor로 쓰기 준비 상태 이벤트 식별에 사용되는 비트마스트 상수. |
BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT | Reactor로 오류 준비 상태 이벤트 식별에 사용되는 비트마스트 상수. |
BOOST_ASIO_HANDLER_REACTOR_EVENTS(args) | Reactor에 등록된 개체가 준비되면 호출되는 표현식이다. args는 소유한 실행 컨텍스트, 고유한 등록 키 및 준비 이벤트에 대한 비트마스트를 포함하는 괄호로 묶인 함수 인수 목록이다. |
BOOST_ASIO_HANDLER_REACTOR_OPERATION(args) | Reactor 기반 비동기식 작업의 일부로 시스템 호출을 수행하는 구현에서 호출하는 표현식이다. args는 추적 핸들러, 작업 이름, 작업에서 생성된 오류 코드 및 (선택적으로)전송된 바이트 수를 포함하는 괄호로 묶인 함수 인수 목록이다. |
더 보기
'Boost C++ Libraries > Boost.Asio' 카테고리의 다른 글
Boost.Asio 개요 - 핵심 개념 및 기능 - 스택리스 코-루틴 (0) | 2020.12.09 |
---|---|
Boost.Asio 개요 - 핵심 개념 및 기능 - 동시성 힌트 (0) | 2020.12.09 |
Boost.Asio 개요 - 핵심 개념 및 기능 - 사용자 지정 메모리 할당 (0) | 2020.12.08 |
Boost.Asio 개요 - 핵심 개념 및 기능 - 라인 기반 작업 (0) | 2020.12.08 |
Boost.Asio 개요 - 핵심 개념 및 기능 - Reactor 스타일 작업 (0) | 2020.12.08 |