From 8bd6e5b92d50e15235f2777ea715aaea75c2886e Mon Sep 17 00:00:00 2001 From: Takamasa Takenaka Date: Thu, 12 Oct 2023 19:21:44 -0300 Subject: [PATCH] Validate fm manager socket fd before send a message When fm manager is restarted, there is no mechanism to detect it from fm api client side. As a result, when subcloud delete clear alarm request is sent after fm manager is restarted, fm api client will show broke pipe and clear alarm request is not received and this alarm stays. This fix is to check socket fd state before send/receive from fm api client. If broken pipe is detected, it will try to reconnect to fm manager. Closes-bug: 2039684 Test Plan: PASS: Restart fm manager and confirm that detect broken pipe and reconnect messages in /var/log. For example, ----- sm: err fmSocket.cpp(270): A broken pipe error occurred sm: warning fmAPI.cpp(116): Invalid file descriptor. Atte mpting to reconnect... sm: info fmAPI.cpp(149): Connected to FM Manager. ----- PASS: Delete offline subcloud and confirm the alarm is removed. Change-Id: Ibc0f4d96b5c0a385d8fedbc1acd23898f1cbea46 Signed-off-by: Takamasa Takenaka --- fm-common/sources/fmAPI.cpp | 14 +++++++++++++- fm-common/sources/fmSocket.cpp | 18 +++++++++++++++++- fm-common/sources/fmSocket.h | 3 ++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/fm-common/sources/fmAPI.cpp b/fm-common/sources/fmAPI.cpp index a52f2f86..5f3613ba 100644 --- a/fm-common/sources/fmAPI.cpp +++ b/fm-common/sources/fmAPI.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Wind River Systems, Inc. +// Copyright (c) 2017,2023 Wind River Systems, Inc. // // SPDX-License-Identifier: Apache-2.0 // @@ -106,6 +106,18 @@ static bool dequeue(fm_buff_t &req) { static bool fm_lib_reconnect() { char addr[INET6_ADDRSTRLEN]; + if (m_connected) { + // Check fd is valid + // When fm manager is restarted, it is possible to + // have broken pipe. This checks fd is valid or not. + // If not, set m_connected false, so that it will + // try to connect in the following while loop. + if (!m_client.fd_valid()) { + FM_WARNING_LOG("Invalid file descriptor. Attempting to reconnect..."); + m_connected = false; + } + } + while (!m_connected) { struct addrinfo hints; struct addrinfo *result = NULL, *rp; diff --git a/fm-common/sources/fmSocket.cpp b/fm-common/sources/fmSocket.cpp index e14e62d5..831418c1 100644 --- a/fm-common/sources/fmSocket.cpp +++ b/fm-common/sources/fmSocket.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Wind River Systems, Inc. +// Copyright (c) 2017,2023 Wind River Systems, Inc. // // SPDX-License-Identifier: Apache-2.0 // @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -259,6 +260,21 @@ int CFmSocket::select_read(int fd,int timeout, bool &timedout){ return select(&fd,1,NULL,0,timeout,0,timedout); } +bool CFmSocket::fd_valid(){ + struct pollfd pfd = {.fd = m_fd, .events = POLLRDHUP}; + if ((poll(&pfd, 1, 0)) < 0) { + return false; + } else { + if (pfd.revents & POLLRDHUP) { + // broken pipe + FM_ERROR_LOG("A broken pipe error occurred\n"); + return false; + } else { + return true; + } + } +} + bool CFmSocket::recvfrom(void *data, long &len, CFmSockAddr &addr) { socklen_t addr_len = sizeof(addr.address); int l = ::recvfrom(m_fd,data,len,0,addr.get_sockaddr(),&addr_len); diff --git a/fm-common/sources/fmSocket.h b/fm-common/sources/fmSocket.h index f960e548..48a9289b 100644 --- a/fm-common/sources/fmSocket.h +++ b/fm-common/sources/fmSocket.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 Wind River Systems, Inc. +// Copyright (c) 2014,2023 Wind River Systems, Inc. // // SPDX-License-Identifier: Apache-2.0 // @@ -67,6 +67,7 @@ public: int get_fd() { return m_fd; } + bool fd_valid(); bool recvfrom(void *data, long &len, CFmSockAddr &addr ); static int select(int *rfd, int rlen, int *wfds, int wlen,int timeout,int timeoutusec, bool &timedout);