From 83f6d02eb58f5b821838445683ae6a70c6000e3e Mon Sep 17 00:00:00 2001 From: shihchienc Date: Sun, 22 Sep 2024 08:37:43 +0000 Subject: [PATCH] threadhal: handle socket disconnection gracefully Thread hal exit the process when receiving socket disconnection. This patch is to change the behavior to handle this connection gracefully. Bug: 368867685 Test: atest VtsHalThreadNetworkTargetTest Test: manual Change-Id: I04a9b00784c4c4beb4dad97d080532a3052be05a --- .../aidl/default/socket_interface.cpp | 57 +++++++++++++------ .../aidl/default/socket_interface.hpp | 10 ++++ 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/threadnetwork/aidl/default/socket_interface.cpp b/threadnetwork/aidl/default/socket_interface.cpp index a5aa2b42b2..71c6b4f1b6 100644 --- a/threadnetwork/aidl/default/socket_interface.cpp +++ b/threadnetwork/aidl/default/socket_interface.cpp @@ -36,6 +36,7 @@ #include #include "common/code_utils.hpp" +#include "openthread/error.h" #include "openthread/openthread-system.h" #include "platform-posix.h" @@ -56,14 +57,9 @@ SocketInterface::SocketInterface(const ot::Url::Url& aRadioUrl) otError SocketInterface::Init(ReceiveFrameCallback aCallback, void* aCallbackContext, RxFrameBuffer& aFrameBuffer) { - otError error = OT_ERROR_NONE; + otError error = InitSocket(); - VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY); - - WaitForSocketFileCreated(mRadioUrl.GetPath()); - - mSockFd = OpenFile(mRadioUrl); - VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED); + VerifyOrExit(error == OT_ERROR_NONE); mReceiveFrameCallback = aCallback; mReceiveFrameContext = aCallbackContext; @@ -155,9 +151,22 @@ otError SocketInterface::WaitForHardwareResetCompletion(uint32_t aTimeoutMs) { VerifyOrExit(!mIsHardwareResetting, error = OT_ERROR_FAILED); - WaitForSocketFileCreated(mRadioUrl.GetPath()); - mSockFd = OpenFile(mRadioUrl); - VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED); +exit: + return error; +} + +otError SocketInterface::InitSocket() { + otError error = OT_ERROR_NONE; + int retries = 0; + + VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY); + + while (retries++ < kMaxRetriesForSocketInit) { + WaitForSocketFileCreated(mRadioUrl.GetPath()); + mSockFd = OpenFile(mRadioUrl); + VerifyOrExit(mSockFd == -1); + } + error = OT_ERROR_FAILED; exit: return error; @@ -168,11 +177,16 @@ void SocketInterface::UpdateFdSet(void* aMainloopContext) { assert(context != nullptr); + VerifyOrExit(mSockFd != -1); + FD_SET(mSockFd, &context->mReadFdSet); if (context->mMaxFd < mSockFd) { context->mMaxFd = mSockFd; } + +exit: + return; } void SocketInterface::Process(const void* aMainloopContext) { @@ -181,9 +195,14 @@ void SocketInterface::Process(const void* aMainloopContext) { assert(context != nullptr); + VerifyOrExit(mSockFd != -1); + if (FD_ISSET(mSockFd, &context->mReadFdSet)) { Read(); } + +exit: + return; } otError SocketInterface::HardwareReset(void) { @@ -198,22 +217,24 @@ otError SocketInterface::HardwareReset(void) { void SocketInterface::Read(void) { uint8_t buffer[kMaxFrameSize]; + ssize_t rval; - ssize_t rval = TEMP_FAILURE_RETRY(read(mSockFd, buffer, sizeof(buffer))); + VerifyOrExit(mSockFd != -1); + + rval = TEMP_FAILURE_RETRY(read(mSockFd, buffer, sizeof(buffer))); if (rval > 0) { ProcessReceivedData(buffer, static_cast(rval)); } else if (rval < 0) { DieNow(OT_EXIT_ERROR_ERRNO); } else { - if (mIsHardwareResetting) { - LogInfo("Socket connection is closed due to hardware reset."); - ResetStates(); - } else { - LogCrit("Socket connection is closed by remote."); - exit(OT_EXIT_FAILURE); - } + LogWarn("Socket connection is closed by remote, isHardwareReset: %d", mIsHardwareResetting); + ResetStates(); + InitSocket(); } + +exit: + return; } void SocketInterface::Write(const uint8_t* aFrame, uint16_t aLength) { diff --git a/threadnetwork/aidl/default/socket_interface.hpp b/threadnetwork/aidl/default/socket_interface.hpp index 494d76ad5a..83c86e88b9 100644 --- a/threadnetwork/aidl/default/socket_interface.hpp +++ b/threadnetwork/aidl/default/socket_interface.hpp @@ -246,6 +246,15 @@ class SocketInterface : public ot::Spinel::SpinelInterface, */ otError WaitForHardwareResetCompletion(uint32_t aTimeoutMs); + /** + * Initialize socket + * + * @retval TRUE Socket initialization is successful. + * @retval FALSE Socket initialization is failed. + * + */ + otError InitSocket(); + /** * Reset socket interface to intitial state. * @@ -257,6 +266,7 @@ class SocketInterface : public ot::Spinel::SpinelInterface, ///< descriptor to become available. kMaxRetriesForSocketCloseCheck = 3, ///< Maximum retry times for checking ///< if socket is closed. + kMaxRetriesForSocketInit = 3, ///< Maximum retry times for socket initialization. }; ReceiveFrameCallback mReceiveFrameCallback;