2014-02-19 1 views
8

이 게시물은 최근 소프트웨어 프로젝트에서 발생한 기술적 인 문제와 관련이 있으며 독자가 어려운 솔루션에서 이익을 얻을 수 있도록합니다. 문제. 내 회사에서유효하지 않은 소켓을 사용하여 boost :: asio :: write()를 호출하면 Blackberry 10 응용 프로그램이 다운 됨

배경

, 나는 소켓을 통해 크로스 플랫폼 데이터 전송을 달성하기 위해 Boost asio ("ASynchronous I/O") socket framework를 사용하는 내부 라이브러리의 구현 및 메인테이너입니다. 동료가 최근에 다음과 같은 문제로 저를 보았습니다. 파일 전송 작업 중에 Wi-Fi 라우터가 갑자기 꺼지면 몇 초 안에 오류가 발생하여 내 라이브러리를 연결하고 사용한 Blackberry 10 응용 프로그램이 다운되었습니다.

라이브러리에서 내장 추적 기능을 사용하면 라이브러리에서 boost :: asio :: write (boost :: asio :: ip :: tcp :: socket *, boost :: asio :: buffer) 함수는 '유효하지 않은'소켓을 가지고있다. (즉, 소켓을 사용할 수 없다.) write() 주변에 try/catch (boost :: system :: system_error) 블록을 놓는 것은 아무 것도 잡지 못했습니다. Boost에서 충돌이 발생했습니다.

크래시가 릴리스 빌드에서만 발생했기 때문에 디버거를 사용할 수 없었습니다.

기술 정보는

  • QNX 컴파일러 QCC는
  • 사용 부스트 버전 GNU 4.6.3 여기

1.48.0 전형적인 명령 행 호출이다 사용 컴파일러의 :

/home/foobar/bbndk/host_10_1_0_238/linux/x86/usr/bin/QCC 
    -Vgcc_ntoarmv7le 
    -lang-c++ 
    -x c++ 
    -DLINUX -DQNX -DSUPPORT_LAN -DUSE_SQLITE_FOR_DATABASE 
    -Wno-psabi -Wno-write-strings 
    -O3 
    -DNDEBUG 
    -fno-strict-aliasing 
    -fPIC 
    -I/home/foobar/Libraries/BlackBerry_10/boost_1.48/include 
    ... 
    -I/home/foobar/Libraries/BlackBerry_10/utfcpp_1.0/include 
    -o CMakeFiles/Internals.dir/ConfigFileSingleton.cpp.o 
    -c /home/foobar/myproject_dev/myproject/SDK/Internals/ConfigFileSingleton.cpp 

문제점 소스를 찾는 데 사용되는 단계

우리는 가벼운 최소 응용 프로그램을 작성하여 원시 코드를 사용하여 문제를 재현하고 Boost의 ASIO를 사용했습니다. 충돌이 발생했다면 우리의 독점적 인 라이브러리로 인해 문제가 발생한 것으로 추측 할 수있었습니다. 불행히도, 충돌은 재현 할 수 없었기 때문에 우리 도서관이 잘못되었다고 의심하게되었습니다.

우리는 Boost의 ASIO 헤더 파일에 사용하기 위해 경량 추적 프레임 워크를 작성하여 문제와 관련된 기능을 계측했습니다. 프레임 워크는 이러한 함수로 들어오고 나가는 문자열을 출력하여 변수의 값도 추적 할 수있었습니다.

추적 프레임 워크를 사용하여 boost :: throw_exception() 템플릿 함수 (관련이없는 # ifdef'd 코드 제거됨)에서 충돌이 발생했음을 증명할 수있었습니다.

template<class E> BOOST_ATTRIBUTE_NORETURN inline void throw_exception(E const & e) 
{ 
    //All boost exceptions are required to derive from std::exception, 
    //to ensure compatibility with BOOST_NO_EXCEPTIONS. 
    throw_exception_assert_compatibility(e); 
    throw enable_current_exception(enable_error_info(e)); 
} 

트레이스를 삽입하고 충돌하는 과정에서 발생하는 것을 우리에게 증명 별도의 문으로 '던져'문을 분할 : 시스템 수준의 쓰기 작업이 실패 할 때 부스트는 "깨진 파이프"에이 함수를 호출 예외 객체를 던집니다. 예외가 던져 질 때 스택의 풀기에 무언가가 매우 잘못 될 수있었습니다.우리는 오히려 응용 프로그램 수준 일보다, 대부분의 아마 컴파일러의 버그가 있었다 실현되면

솔루션

, 우리는 라이브러리를 빌드하는 데 사용되는 컴파일러 옵션을 조사했다. 우리는 Boost 내부 코드가 아마도 견고하고 견고하기 때문에 메모리 손상을 배제했습니다. 릴리즈 모드 최적화가 원인 일 수 있다고 생각한 후에는 거리가 솔루션에 미치지 못했습니다. 최적화 수준을 -O3에서 -O2로 낮 춥니 다.

일단 우리가 그 충돌이 증발하면.

"-O2"보다는 원래 "-03"를 사용하는 QNX 툴체인에 Blackberry.cmake 파일을 수정하기 때문에 우리는이 : 그것은하는 것이 좋습니다 수 있습니다이 충돌의 관점에서

SET(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG") 
#SET(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 
. . . 
SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG -fno-strict-aliasing -fPIC") 
#SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -fno-strict-aliasing -fPIC") 

을 주의해서 "-O3"을 사용하십시오. 최소 응용 프로그램이 문제를 재현하지 못한 이유는 3이 아닌 최적화 수준 2로 컴파일 되었기 때문입니다.

QNX 및/또는 GNU 팀에 제출할 때 SSCCE을 찾고 있습니다.

+1

해결책을 답안을 "답변되지 않은 질문"에 표시되지 않도록 입력하십시오. 질문의 목적이 지식을 공유하는 것이기 때문에 자신의 질문에 "StackOverflow"에서 "좋은 일"으로 간주됩니다. –

+0

@Dale 헤드 업과 방향에 감사드립니다. "답이없는 질문"문제를 방지하기위한 답으로 해결책에 대한 간단한 요약을 게시하고 있으며 앞으로 "옳은 일"이 될 것입니다 . 다시 한번 감사드립니다. –

답변

1

전체 솔루션 설명은 위의 질문에서 찾을 수 있습니다. 데일 (Dale)의 포인터에 따르면, 여기에 해결책에 대한 간단한 설명이 나와 있습니다.

기본 최적화 수준 3을 사용하여 부스트를 컴파일하는 것이 원인이었습니다. 최적화 수준을 -O3에서 -O2로 떨어 뜨리면 충돌이 사라졌습니다.

이후 QNX 툴체인의 Blackberry.cmake 파일을 수정하여 원래 "-O3"대신 "-O2"를 사용했습니다. 이 충돌에 비추어 "-O3"을 신중히 사용하는 것이 좋습니다.