[posix-host] die on RCP timeout (#4591)

When RCP fails to respond in time, it usually means RCP is stuck or in
some bad situations that can only recover by hardware resetting. This
commit changes the behavior on RCP timeout so that RCP can be reset
during the host daemon restarting.
This commit is contained in:
Yakun Xu
2020-02-24 20:58:34 -08:00
committed by GitHub
parent 24a24f1f9e
commit ff3033f24f
4 changed files with 26 additions and 26 deletions
+6 -5
View File
@@ -250,13 +250,12 @@ exit:
otError HdlcInterface::WaitForFrame(const struct timeval &aTimeout)
{
otError error = OT_ERROR_NONE;
struct timeval timeout = aTimeout;
otError error = OT_ERROR_NONE;
#if OPENTHREAD_POSIX_VIRTUAL_TIME
struct Event event;
uint64_t delay = static_cast<uint64_t>(aTimeout.tv_sec) * US_PER_S + static_cast<uint64_t>(aTimeout.tv_usec);
virtualTimeSendSleepEvent(&timeout);
virtualTimeSendSleepEvent(&aTimeout);
virtualTimeReceiveEvent(&event);
switch (event.mEvent)
@@ -266,7 +265,7 @@ otError HdlcInterface::WaitForFrame(const struct timeval &aTimeout)
break;
case OT_SIM_EVENT_ALARM_FIRED:
ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
VerifyOrExit(event.mDelay <= delay, error = OT_ERROR_RESPONSE_TIMEOUT);
break;
default:
@@ -274,6 +273,8 @@ otError HdlcInterface::WaitForFrame(const struct timeval &aTimeout)
break;
}
#else // OPENTHREAD_POSIX_VIRTUAL_TIME
struct timeval timeout = aTimeout;
fd_set read_fds;
fd_set error_fds;
int rval;
@@ -82,6 +82,11 @@ enum
* System call or library function error.
*/
OT_EXIT_ERROR_ERRNO = 5,
/**
* No response from radio spinel.
*/
OT_EXIT_RADIO_SPINEL_NO_RESPONSE = 6,
};
/**
+4
View File
@@ -133,6 +133,10 @@ const char *otExitCodeToString(uint8_t aExitCode)
retval = "RadioSpinelReset";
break;
case OT_EXIT_RADIO_SPINEL_NO_RESPONSE:
retval = "RadioSpinelNoResponse";
break;
case OT_EXIT_ERROR_ERRNO:
retval = strerror(errno);
break;
+11 -21
View File
@@ -1237,36 +1237,26 @@ otError RadioSpinel::Remove(spinel_prop_key_t aKey, const char *aFormat, ...)
otError RadioSpinel::WaitResponse(void)
{
uint64_t now = platformGetTime();
uint64_t end = now + kMaxWaitTime * US_PER_MS;
struct timeval timeout = {kMaxWaitTime / 1000, (kMaxWaitTime % 1000) * 1000};
uint64_t end = platformGetTime() + kMaxWaitTime * US_PER_MS;
otLogInfoPlat("Wait response: tid=%u key=%u", mWaitingTid, mWaitingKey);
do
{
if (mSpinelInterface.WaitForFrame(timeout) == OT_ERROR_RESPONSE_TIMEOUT)
{
FreeTid(mWaitingTid);
mWaitingTid = 0;
ExitNow(mError = OT_ERROR_RESPONSE_TIMEOUT);
}
uint64_t now;
uint64_t remain;
struct timeval timeout;
now = platformGetTime();
VerifyOrDie(end > now, OT_EXIT_RADIO_SPINEL_NO_RESPONSE);
remain = end - now;
if (end > now)
{
uint64_t remain = end - now;
timeout.tv_sec = static_cast<time_t>(remain / US_PER_S);
timeout.tv_usec = static_cast<suseconds_t>(remain % US_PER_S);
timeout.tv_sec = static_cast<time_t>(remain / US_PER_S);
timeout.tv_usec = static_cast<suseconds_t>(remain % US_PER_S);
}
else
{
mWaitingTid = 0;
mError = OT_ERROR_RESPONSE_TIMEOUT;
}
VerifyOrDie(mSpinelInterface.WaitForFrame(timeout) == OT_ERROR_NONE, OT_EXIT_RADIO_SPINEL_NO_RESPONSE);
} while (mWaitingTid || !mIsReady);
exit:
LogIfFail("Error waiting response", mError);
// This indicates end of waiting repsonse.
mWaitingKey = SPINEL_PROP_LAST_STATUS;