diff --git a/src/posix/client.cpp b/src/posix/client.cpp index 2b93d4883..2078d8c8d 100644 --- a/src/posix/client.cpp +++ b/src/posix/client.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #if HAVE_LIBEDIT @@ -108,17 +109,17 @@ exit: return ret; } -int main(int argc, char *argv[]) +static int ConnectSession(void) { - int ret; - bool isInteractive = true; - bool isFinished = false; - char lineBuffer[kLineBufferSize]; - size_t lineBufferWritePos = 0; - bool isBeginOfLine = true; + int ret; + + if (sSessionFd != -1) + { + close(sSessionFd); + } sSessionFd = socket(AF_UNIX, SOCK_STREAM, 0); - VerifyOrExit(sSessionFd != -1, perror("socket"); ret = OT_EXIT_FAILURE); + VerifyOrExit(sSessionFd != -1, ret = -1); { struct sockaddr_un sockname; @@ -128,14 +129,47 @@ int main(int argc, char *argv[]) strncpy(sockname.sun_path, OPENTHREAD_POSIX_DAEMON_SOCKET_NAME, sizeof(sockname.sun_path) - 1); ret = connect(sSessionFd, reinterpret_cast(&sockname), sizeof(struct sockaddr_un)); - - if (ret == -1) - { - fprintf(stderr, "OpenThread daemon is not running.\n"); - ExitNow(ret = OT_EXIT_FAILURE); - } } +exit: + return ret; +} + +static bool ReconnectSession(void) +{ + bool ok = false; + uint32_t delay = 0; // 100ms + + for (int i = 0; i < 6; i++) // delay for 3.1s in total + { + int rval; + + usleep(delay); + delay = delay > 0 ? delay * 2 : 100000; + + rval = ConnectSession(); + + VerifyOrExit(rval == -1, ok = true); + + // Exit immediately if the sock file is not found + VerifyOrExit(errno != ENOENT, OT_NOOP); + } + +exit: + return ok; +} + +int main(int argc, char *argv[]) +{ + int ret; + bool isInteractive = true; + bool isFinished = false; + char lineBuffer[kLineBufferSize]; + size_t lineBufferWritePos = 0; + bool isBeginOfLine = true; + + VerifyOrExit(ConnectSession() != -1, perror("connect session failed"); ret = OT_EXIT_FAILURE); + if (argc > 1) { for (int i = 1; i < argc; i++) @@ -205,6 +239,11 @@ int main(int argc, char *argv[]) if (rval == 0) { // daemon closed sSessionFd + if (isInteractive && ReconnectSession()) + { + continue; + } + ExitNow(ret = isInteractive ? OT_EXIT_FAILURE : OT_EXIT_SUCCESS); } diff --git a/src/posix/main.c b/src/posix/main.c index 4614d6f3c..054abe819 100644 --- a/src/posix/main.c +++ b/src/posix/main.c @@ -75,6 +75,7 @@ #include #include #include +#include #ifndef OPENTHREAD_ENABLE_COVERAGE #define OPENTHREAD_ENABLE_COVERAGE 0 @@ -264,6 +265,8 @@ static otInstance *InitInstance(int aArgCount, char *aArgVector[]) instance = otSysInit(&config.mPlatformConfig); + atexit(otSysDeinit); + if (config.mPrintRadioVersion) { printf("%s\n", otPlatRadioGetVersionString(instance)); @@ -288,6 +291,8 @@ void otTaskletsSignalPending(otInstance *aInstance) void otPlatReset(otInstance *aInstance) { + gPlatResetReason = OT_PLAT_RESET_REASON_SOFTWARE; + otInstanceFinalize(aInstance); otSysDeinit(); @@ -298,6 +303,7 @@ void otPlatReset(otInstance *aInstance) int main(int argc, char *argv[]) { otInstance *instance; + int rval = 0; #ifdef __linux__ // Ensure we terminate this process if the @@ -356,15 +362,16 @@ int main(int argc, char *argv[]) else if (errno != EINTR) { perror("select"); - exit(OT_EXIT_FAILURE); + ExitNow(rval = OT_EXIT_FAILURE); } } #ifdef OPENTHREAD_USE_CONSOLE otxConsoleDeinit(); #endif - otInstanceFinalize(instance); - otSysDeinit(); - return 0; +exit: + otInstanceFinalize(instance); + + return rval; } diff --git a/src/posix/platform/include/openthread/openthread-system.h b/src/posix/platform/include/openthread/openthread-system.h index 27c75f479..6e45fa540 100644 --- a/src/posix/platform/include/openthread/openthread-system.h +++ b/src/posix/platform/include/openthread/openthread-system.h @@ -43,6 +43,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -151,6 +152,8 @@ void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMa */ const char *otSysGetRadioUrlHelpString(void); +extern otPlatResetReason gPlatResetReason; + #ifdef __cplusplus } // end of extern "C" #endif diff --git a/src/posix/platform/misc.cpp b/src/posix/platform/misc.cpp index 0251b7a1e..ee9825442 100644 --- a/src/posix/platform/misc.cpp +++ b/src/posix/platform/misc.cpp @@ -40,14 +40,14 @@ #include "common/code_utils.hpp" #include "common/logging.hpp" -static otPlatResetReason sPlatResetReason = OT_PLAT_RESET_REASON_POWER_ON; +otPlatResetReason gPlatResetReason = OT_PLAT_RESET_REASON_POWER_ON; static otPlatMcuPowerState gPlatMcuPowerState = OT_PLAT_MCU_POWER_STATE_ON; otPlatResetReason otPlatGetResetReason(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); - return sPlatResetReason; + return gPlatResetReason; } void otPlatWakeHost(void) diff --git a/src/posix/platform/uart.cpp b/src/posix/platform/uart.cpp index 7f6e8d857..3875b29f3 100644 --- a/src/posix/platform/uart.cpp +++ b/src/posix/platform/uart.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include "common/code_utils.hpp" @@ -137,6 +138,12 @@ otError otPlatUartDisable(void) sUartSocket = -1; } + if (gPlatResetReason != OT_PLAT_RESET_REASON_SOFTWARE) + { + otLogCritPlat("Removing daemon socket: %s", OPENTHREAD_POSIX_DAEMON_SOCKET_NAME); + (void)unlink(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME); + } + if (sUartLock != -1) { (void)flock(sUartLock, LOCK_UN); diff --git a/tests/scripts/expect/cli-reset.exp b/tests/scripts/expect/cli-reset.exp new file mode 100755 index 000000000..48fa8f602 --- /dev/null +++ b/tests/scripts/expect/cli-reset.exp @@ -0,0 +1,68 @@ +#!/usr/bin/expect -f +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +source "tests/scripts/expect/_common.exp" + +set spawn_id [spawn_node 1] + +send "ifconfig up\n" +expect "Done" +send "panid 0xabcd\n" +expect "Done" +send "thread start\n" +expect "Done" + +sleep 3 + +send "reset\n" +sleep 3 + +send "ifconfig\n" +expect "down" +expect "Done" +send "panid\n" +expect "0xabcd" +expect "Done" + +send "ifconfig up\n" +expect "Done" +send "thread start\n" +expect "Done" + +send "factoryreset\n" +sleep 3 + +send "ifconfig\n" +expect "down" +expect "Done" +send "panid\n" +expect "0xffff" +expect "Done" + +dispose