From a97a0be5f16cb876d7226b733ac6aaa3b79dabd3 Mon Sep 17 00:00:00 2001 From: Sadik Armagan Date: Tue, 3 Mar 2020 10:44:56 +0000 Subject: IVGCVSW-4163 Enhance the error handling in the ReadPacket function * Introduced armnn::SocketConnectionException with fields error no and socket info. Signed-off-by: Sadik Armagan Change-Id: Ideb85b00771864e332226635aeff3096fbea8e5f --- Android.mk | 4 ++ CMakeLists.txt | 1 + cmake/GlobalConfig.cmake | 1 + .../common/include/SocketConnectionException.hpp | 51 ++++++++++++++++ src/profiling/ProfilingService.cpp | 6 ++ src/profiling/SocketProfilingConnection.cpp | 71 +++++++++++++++++----- src/profiling/test/ProfilingTests.cpp | 22 ++++++- 7 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 profiling/common/include/SocketConnectionException.hpp diff --git a/Android.mk b/Android.mk index e29f0f913e..c63022c3aa 100644 --- a/Android.mk +++ b/Android.mk @@ -9,6 +9,7 @@ LOCAL_PATH := $(call my-dir) OPENCL_HEADER_PATH := $(LOCAL_PATH)/../clframework/include NN_HEADER_PATH := $(LOCAL_PATH)/../../../../frameworks/ml/nn/runtime/include ARMNN_HEADER_PATH := $(LOCAL_PATH)/include +ARMNN_PROFILING_INCLUDE_PATH := $(LOCAL_PATH)/profiling ARMNN_MAIN_HEADER_PATH := $(LOCAL_PATH)/src ARMNN_SOURCE_HEADER_PATH := $(LOCAL_PATH)/src/armnn ARMNN_SOURCE_UTILS_HEADER_PATH := $(LOCAL_PATH)/src/armnnUtils @@ -64,6 +65,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk \ LOCAL_EXPORT_C_INCLUDES := \ $(ARMNN_MAIN_HEADER_PATH) \ $(ARMNN_SOURCE_HEADER_PATH) \ + $(ARMNN_PROFILING_INCLUDE_PATH) \ $(ARMNN_SOURCE_UTILS_HEADER_PATH) \ $(ARMNN_PROFILING_HEADER_PATH) \ $(ARMNN_BACKENDS_HEADER_PATH) @@ -72,6 +74,7 @@ LOCAL_C_INCLUDES := \ $(OPENCL_HEADER_PATH) \ $(NN_HEADER_PATH) \ $(ARMNN_HEADER_PATH) \ + $(ARMNN_PROFILING_INCLUDE_PATH) \ $(ARMNN_MAIN_HEADER_PATH) \ $(ARMNN_SOURCE_HEADER_PATH) \ $(ARMNN_SOURCE_UTILS_HEADER_PATH) \ @@ -290,6 +293,7 @@ LOCAL_C_INCLUDES := \ $(OPENCL_HEADER_PATH) \ $(NN_HEADER_PATH) \ $(ARMNN_HEADER_PATH) \ + $(ARMNN_PROFILING_INCLUDE_PATH) \ $(ARMNN_MAIN_HEADER_PATH) \ $(ARMNN_SOURCE_HEADER_PATH) \ $(ARMNN_SOURCE_UTILS_HEADER_PATH) \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ab89a4ed3..e3b794ab53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -247,6 +247,7 @@ list(APPEND armnn_sources include/armnn/Version.hpp include/armnn/profiling/IProfilingGuidGenerator.hpp include/armnn/profiling/ISendTimelinePacket.hpp + profiling/common/include/SocketConnectionException.hpp src/armnn/layers/LayerCloneBase.hpp src/armnn/layers/LayerWithParameters.hpp src/armnn/layers/ActivationLayer.hpp diff --git a/cmake/GlobalConfig.cmake b/cmake/GlobalConfig.cmake index 8e3b68d1b1..1fb86e930d 100644 --- a/cmake/GlobalConfig.cmake +++ b/cmake/GlobalConfig.cmake @@ -209,6 +209,7 @@ if(BUILD_ARMNN_SERIALIZER) endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/profiling) # ARM Compute # Note that ARM Compute has a different folder layout depending on the branch but also on diff --git a/profiling/common/include/SocketConnectionException.hpp b/profiling/common/include/SocketConnectionException.hpp new file mode 100644 index 0000000000..58b8a14d6d --- /dev/null +++ b/profiling/common/include/SocketConnectionException.hpp @@ -0,0 +1,51 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include +#include +#include + +namespace armnnProfiling +{ + +/// Socket Connection Exception for profiling +class SocketConnectionException : public std::exception +{ +public: + explicit SocketConnectionException(const std::string& message, int socket) + : m_Message(message), m_Socket(socket), m_ErrNo(-1) + {}; + + explicit SocketConnectionException(const std::string& message, int socket, int errNo) + : m_Message(message), m_Socket(socket), m_ErrNo(errNo) + {}; + + /// @return - Error message of SocketProfilingConnection + virtual const char* what() const noexcept override + { + return m_Message.c_str(); + } + + /// @return - Socket File Descriptor of SocketProfilingConnection + /// or '-1', an invalid file descriptor + int GetSocketFd() const noexcept + { + return m_Socket; + } + + /// @return - errno of SocketProfilingConnection + int GetErrorNo() const noexcept + { + return m_ErrNo; + } + +private: + std::string m_Message; + int m_Socket; + int m_ErrNo; +}; + +} // namespace armnnProfiling diff --git a/src/profiling/ProfilingService.cpp b/src/profiling/ProfilingService.cpp index 0c33ca0e7d..f111de15db 100644 --- a/src/profiling/ProfilingService.cpp +++ b/src/profiling/ProfilingService.cpp @@ -7,6 +7,7 @@ #include #include +#include #include @@ -128,6 +129,11 @@ void ProfilingService::Update() ARMNN_LOG(warning) << "An error has occurred when creating the profiling connection: " << e.what(); } + catch (const armnnProfiling::SocketConnectionException& e) + { + ARMNN_LOG(warning) << "An error has occurred when creating the profiling connection [" + << e.what() << "] on socket [" << e.GetSocketFd() << "]."; + } // Move to the next state m_StateMachine.TransitionToState(m_ProfilingConnection diff --git a/src/profiling/SocketProfilingConnection.cpp b/src/profiling/SocketProfilingConnection.cpp index 4bbbc2962c..31f930be84 100644 --- a/src/profiling/SocketProfilingConnection.cpp +++ b/src/profiling/SocketProfilingConnection.cpp @@ -5,6 +5,8 @@ #include "SocketProfilingConnection.hpp" +#include "common/include/SocketConnectionException.hpp" + #include #include #include @@ -24,7 +26,10 @@ SocketProfilingConnection::SocketProfilingConnection() m_Socket[0].fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (m_Socket[0].fd == -1) { - throw armnn::RuntimeException(std::string("Socket construction failed: ") + strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Socket construction failed: ") + strerror(errno), + m_Socket[0].fd, + errno); } // Connect to the named unix domain socket. @@ -36,7 +41,10 @@ SocketProfilingConnection::SocketProfilingConnection() if (0 != connect(m_Socket[0].fd, reinterpret_cast(&server), sizeof(sockaddr_un))) { Close(); - throw armnn::RuntimeException(std::string("Cannot connect to stream socket: ") + strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Cannot connect to stream socket: ") + strerror(errno), + m_Socket[0].fd, + errno); } // Our socket will only be interested in polling reads. @@ -46,7 +54,10 @@ SocketProfilingConnection::SocketProfilingConnection() if (!Sockets::SetNonBlocking(m_Socket[0].fd)) { Close(); - throw armnn::RuntimeException(std::string("Failed to set socket as non blocking: ") + strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Failed to set socket as non blocking: ") + strerror(errno), + m_Socket[0].fd, + errno); } } @@ -59,7 +70,10 @@ void SocketProfilingConnection::Close() { if (Sockets::Close(m_Socket[0].fd) != 0) { - throw armnn::RuntimeException(std::string("Cannot close stream socket: ") + strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Cannot close stream socket: ") + strerror(errno), + m_Socket[0].fd, + errno); } memset(m_Socket, 0, sizeof(m_Socket)); @@ -92,10 +106,13 @@ Packet SocketProfilingConnection::ReadPacket(uint32_t timeout) switch (pollResult) { case -1: // Error - throw armnn::RuntimeException(std::string("Read failure from socket: ") + strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Error occured while reading from socket: ") + strerror(errno), + m_Socket[0].fd, + errno); case 0: // Timeout - throw TimeoutException("Timeout while reading from socket"); + throw TimeoutException("SocketProfilingConnection: Timeout while reading from socket"); default: // Normal poll return but it could still contain an error signal // Check if the socket reported an error @@ -105,18 +122,26 @@ Packet SocketProfilingConnection::ReadPacket(uint32_t timeout) { // This is an unrecoverable error. Close(); - throw armnn::RuntimeException(std::string("Error while polling receiving socket: POLLNVAL")); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Error occured while polling receiving socket: POLLNVAL."), + m_Socket[0].fd); } if (m_Socket[0].revents == POLLERR) { - throw armnn::RuntimeException(std::string("Error while polling receiving socket: POLLERR: ") + - strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string( + "SocketProfilingConnection: Error occured while polling receiving socket: POLLERR: ") + + strerror(errno), + m_Socket[0].fd, + errno); } if (m_Socket[0].revents == POLLHUP) { // This is an unrecoverable error. Close(); - throw armnn::RuntimeException(std::string("Connection closed by remote client: POLLHUP")); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Connection closed by remote client: POLLHUP."), + m_Socket[0].fd); } } @@ -125,7 +150,8 @@ Packet SocketProfilingConnection::ReadPacket(uint32_t timeout) { // This is a corner case. The socket as been woken up but not with any data. // We'll throw a timeout exception to loop around again. - throw armnn::TimeoutException("File descriptor was polled but no data was available to receive."); + throw armnn::TimeoutException( + "SocketProfilingConnection: File descriptor was polled but no data was available to receive."); } return ReceivePacket(); @@ -142,15 +168,23 @@ Packet SocketProfilingConnection::ReceivePacket() case 0: // Socket has closed. Close(); - throw armnn::RuntimeException("Remote socket has closed the connection."); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Remote socket has closed the connection."), + m_Socket[0].fd); case -1: // There's been a socket error. We will presume it's unrecoverable. Close(); - throw armnn::RuntimeException(std::string("Error occured on recv: ") + strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Error occured while reading the packet: ") + strerror(errno), + m_Socket[0].fd, + errno); default: if (receiveResult < 8) { - throw armnn::RuntimeException("The received packet did not contains a valid MIPE header"); + throw armnnProfiling::SocketConnectionException( + std::string( + "SocketProfilingConnection: The received packet did not contains a valid PIPE header."), + m_Socket[0].fd); } break; } @@ -170,12 +204,17 @@ Packet SocketProfilingConnection::ReceivePacket() long receivedLength = Sockets::Read(m_Socket[0].fd, packetData.get(), dataLength); if (receivedLength < 0) { - throw armnn::RuntimeException(std::string("Error occurred on recv: ") + strerror(errno)); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Error occured while reading the packet: ") + strerror(errno), + m_Socket[0].fd, + errno); } if (dataLength != static_cast(receivedLength)) { // What do we do here if we can't read in a full packet? - throw armnn::RuntimeException("Invalid MIPE packet"); + throw armnnProfiling::SocketConnectionException( + std::string("SocketProfilingConnection: Invalid PIPE packet."), + m_Socket[0].fd); } } diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp index 6c1e84b8d0..3dab93d9b8 100644 --- a/src/profiling/test/ProfilingTests.cpp +++ b/src/profiling/test/ProfilingTests.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -1888,10 +1889,25 @@ BOOST_AUTO_TEST_CASE(CheckConnectionAcknowledged) BOOST_CHECK_THROW(differentCommandHandler(packetB), armnn::Exception); } -BOOST_AUTO_TEST_CASE(CheckSocketProfilingConnection) +BOOST_AUTO_TEST_CASE(CheckSocketConnectionException) { - // Check that creating a SocketProfilingConnection results in an exception as the Gator UDS doesn't exist. - BOOST_CHECK_THROW(new SocketProfilingConnection(), armnn::Exception); + // Check that creating a SocketProfilingConnection armnnProfiling in an exception as the Gator UDS doesn't exist. + BOOST_CHECK_THROW(new SocketProfilingConnection(), armnnProfiling::SocketConnectionException); +} + +BOOST_AUTO_TEST_CASE(CheckSocketConnectionException2) +{ + try + { + new SocketProfilingConnection(); + } + catch (armnnProfiling::SocketConnectionException& ex) + { + BOOST_CHECK(ex.GetSocketFd() == 0); + BOOST_CHECK(ex.GetErrorNo() == 111); + BOOST_CHECK(ex.what() + == std::string("SocketProfilingConnection: Cannot connect to stream socket: Connection refused")); + } } BOOST_AUTO_TEST_CASE(SwTraceIsValidCharTest) -- cgit v1.2.1