mirror of
https://github.com/espressif/openthread.git
synced 2026-08-23 10:49:51 +00:00
[posix] add UART flush and clean up (#5312)
This commit mainly implements the otPlatUartFlush(). - fix code because MSG_NOSIGNAL is not a macro. - set SO_NOSIGPIPE once.
This commit is contained in:
@@ -173,8 +173,8 @@ jobs:
|
||||
expects:
|
||||
runs-on: ubuntu-18.04
|
||||
env:
|
||||
CFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1
|
||||
CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1
|
||||
CFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
|
||||
CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Bootstrap
|
||||
|
||||
+103
-45
@@ -162,11 +162,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatUartFlush(void)
|
||||
{
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
|
||||
{
|
||||
VerifyOrExit(sEnabled, OT_NOOP);
|
||||
@@ -236,6 +231,19 @@ static void InitializeSessionSocket(void)
|
||||
|
||||
VerifyOrExit((rval = fcntl(sSessionSocket, F_SETFD, rval)) != -1, OT_NOOP);
|
||||
|
||||
#ifndef __linux__
|
||||
// some platforms (macOS, Solaris) don't have MSG_NOSIGNAL
|
||||
// SOME of those (macOS, but NOT Solaris) support SO_NOSIGPIPE
|
||||
// if we have SO_NOSIGPIPE, then set it. Otherwise, we're going
|
||||
// to simply ignore it.
|
||||
#if defined(SO_NOSIGPIPE)
|
||||
rval = 1;
|
||||
VerifyOrExit((rval = setsockopt(sSessionSocket, SOL_SOCKET, SO_NOSIGPIPE, &rval, sizeof(rval)) != -1, OT_NOOP));
|
||||
#else
|
||||
#warning "no support for MSG_NOSIGNAL or SO_NOSIGPIPE"
|
||||
#endif
|
||||
#endif // __linux__
|
||||
|
||||
exit:
|
||||
if (rval == -1)
|
||||
{
|
||||
@@ -249,6 +257,47 @@ exit:
|
||||
}
|
||||
#endif
|
||||
|
||||
static otError UartWrite(int aFd)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
ssize_t rval;
|
||||
|
||||
VerifyOrExit(sWriteLength > 0, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE && defined(__linux__)
|
||||
if (aFd == sSessionSocket)
|
||||
{
|
||||
// Don't die on SIGPIPE
|
||||
rval = send(aFd, sWriteBuffer, sWriteLength, MSG_NOSIGNAL);
|
||||
}
|
||||
else
|
||||
#endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE && defined(__linux__)
|
||||
{
|
||||
rval = write(aFd, sWriteBuffer, sWriteLength);
|
||||
}
|
||||
|
||||
if (rval < 0)
|
||||
{
|
||||
#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
|
||||
otLogWarnPlat("UART write: %s", strerror(errno));
|
||||
if (aFd == sSessionSocket)
|
||||
{
|
||||
close(sSessionSocket);
|
||||
sSessionSocket = -1;
|
||||
}
|
||||
ExitNow();
|
||||
#else
|
||||
DieNow(OT_EXIT_ERROR_ERRNO);
|
||||
#endif
|
||||
}
|
||||
|
||||
sWriteBuffer += rval;
|
||||
sWriteLength -= static_cast<uint16_t>(rval);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, const fd_set *aErrorFdSet)
|
||||
{
|
||||
ssize_t rval;
|
||||
@@ -328,48 +377,11 @@ void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, co
|
||||
fd = STDOUT_FILENO;
|
||||
#endif
|
||||
|
||||
if ((sWriteLength > 0) && (FD_ISSET(fd, aWriteFdSet)))
|
||||
if ((FD_ISSET(fd, aWriteFdSet)))
|
||||
{
|
||||
#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
|
||||
// Don't die on SIGPIPE
|
||||
#if !defined(MSG_NOSIGNAL)
|
||||
// some platforms (mac OS, Solaris) don't have MSG_NOSIGNAL
|
||||
// SOME of those (mac OS, but NOT Solaris) support SO_NOSIGPIPE
|
||||
// if we have SO_NOSIGPIPE, then set it. otherwise, we're going
|
||||
// to simply ignore it.
|
||||
#if defined(SO_NOSIGPIPE)
|
||||
int err;
|
||||
int flag;
|
||||
otError error = UartWrite(fd);
|
||||
|
||||
flag = 1;
|
||||
err = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &flag, sizeof(flag));
|
||||
VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
|
||||
#else
|
||||
#warning "no support for MSG_NOSIGNAL or SO_NOSIGPIPE"
|
||||
#endif
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif // !defined(MSG_NOSIGNAL)
|
||||
rval = send(fd, sWriteBuffer, sWriteLength, MSG_NOSIGNAL);
|
||||
#else
|
||||
rval = write(fd, sWriteBuffer, sWriteLength);
|
||||
#endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
|
||||
|
||||
if (rval < 0)
|
||||
{
|
||||
#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
|
||||
perror("UART write");
|
||||
close(sSessionSocket);
|
||||
sSessionSocket = -1;
|
||||
ExitNow();
|
||||
#else
|
||||
DieNowWithMessage("UART write", OT_EXIT_ERROR_ERRNO);
|
||||
#endif
|
||||
}
|
||||
|
||||
VerifyOrExit(rval > 0, OT_NOOP);
|
||||
|
||||
sWriteBuffer += (uint16_t)rval;
|
||||
sWriteLength -= (uint16_t)rval;
|
||||
VerifyOrExit(error == OT_ERROR_NONE, otLogWarnPlat("UART write: %s", otThreadErrorToString(error)));
|
||||
|
||||
if (sWriteLength == 0)
|
||||
{
|
||||
@@ -380,3 +392,49 @@ void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, co
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError otPlatUartFlush(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
while (sWriteLength > 0)
|
||||
{
|
||||
int fd =
|
||||
#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
|
||||
sSessionSocket != -1 ? sSessionSocket :
|
||||
#endif
|
||||
STDOUT_FILENO;
|
||||
int rval;
|
||||
|
||||
fd_set writeFdSet;
|
||||
FD_ZERO(&writeFdSet);
|
||||
FD_SET(fd, &writeFdSet);
|
||||
|
||||
rval = select(fd + 1, nullptr, &writeFdSet, nullptr, nullptr);
|
||||
|
||||
assert(rval != 0);
|
||||
|
||||
if (rval > 0)
|
||||
{
|
||||
assert(FD_ISSET(fd, &writeFdSet));
|
||||
SuccessOrExit(error = UartWrite(fd));
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
|
||||
if (sSessionSocket == fd)
|
||||
{
|
||||
close(sSessionSocket);
|
||||
sSessionSocket = -1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
DieNow(OT_EXIT_ERROR_ERRNO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#!/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 max_node 15
|
||||
set spawn_ids(1) [spawn_node 1]
|
||||
set spawn_id $spawn_ids(1)
|
||||
expect_after {
|
||||
timeout { exit 1 }
|
||||
}
|
||||
send "panid 0xface\n"
|
||||
expect "Done"
|
||||
send "ifconfig up\n"
|
||||
expect "Done"
|
||||
send "thread start\n"
|
||||
expect "Done"
|
||||
wait_for "state" "leader"
|
||||
expect "Done"
|
||||
|
||||
for {set i 2} {$i <= $max_node} {incr i} {
|
||||
set spawn_ids($i) [spawn_node $i]
|
||||
set spawn_id $spawn_ids($i)
|
||||
expect_after {
|
||||
timeout { exit 1 }
|
||||
}
|
||||
send "mode rs\n"
|
||||
expect "Done"
|
||||
send "panid 0xface\n"
|
||||
expect "Done"
|
||||
send "ifconfig up\n"
|
||||
expect "Done"
|
||||
send "thread start\n"
|
||||
expect "Done"
|
||||
wait_for "state" "child"
|
||||
expect "Done"
|
||||
}
|
||||
|
||||
set spawn_id $spawn_ids(1)
|
||||
expect_after {
|
||||
timeout { exit 1 }
|
||||
}
|
||||
send "child table\n"
|
||||
expect "Done"
|
||||
|
||||
for {set i 1} {$i <= $max_node} {incr i} {
|
||||
set spawn_id $spawn_ids($i)
|
||||
expect_after {
|
||||
timeout { exit 1 }
|
||||
}
|
||||
dispose
|
||||
}
|
||||
Reference in New Issue
Block a user