Boost C++ Libraries/Boost.Asio

Boost.Asio 개요 - 핵심 개념 및 기능 - 핸들러 추적

까마귀75 2020. 12. 9. 11:22
728x90
반응형

핸들러 추적 (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는 추적 핸들러, 작업 이름, 작업에서 생성된 오류 코드 및 (선택적으로)전송된 바이트 수를 포함하는 괄호로 묶인 함수 인수 목록이다.

더 보기

Handler tracking example.

 

 

핵심 개념 및 기능  Boost.Asio 개요  Boost.Asio 홈

728x90
반응형