diff --git a/Source/Components/DataSources/UDPStreamer/UDPStreamer.cpp b/Source/Components/DataSources/UDPStreamer/UDPStreamer.cpp index 06e5340..e724e18 100644 --- a/Source/Components/DataSources/UDPStreamer/UDPStreamer.cpp +++ b/Source/Components/DataSources/UDPStreamer/UDPStreamer.cpp @@ -57,8 +57,11 @@ static const uint32 UDPS_DEFAULT_MAX_PAYLOAD = 1400u; /** Minimum MaxPayloadSize: header + at least 1 byte of payload. */ static const uint32 UDPS_MIN_PAYLOAD = static_cast(sizeof(UDPSPacketHeader)) + 1u; -/** Server socket receive timeout in milliseconds. */ -static const uint32 UDPS_RECV_TIMEOUT_MS = 5u; +/** Server socket receive timeout in milliseconds. + * Set to 0 for a pure non-blocking poll so the send loop can keep pace with + * the RT thread regardless of its frequency. Client commands (CONNECT / + * DISCONNECT) are still caught on the very next loop iteration. */ +static const uint32 UDPS_RECV_TIMEOUT_MS = 0u; /** EventSem wait timeout in milliseconds for the data loop. */ static const uint32 UDPS_DATA_WAIT_MS = 10u; @@ -615,18 +618,24 @@ ErrorManagement::ErrorType UDPStreamer::Execute(ExecutionInfo &info) { } if (info.GetStage() == ExecutionInfo::MainStage) { - /* --- Poll server socket for incoming client commands --- - * Use select() directly so we get a silent timeout with no log spam. - * MARTe2's Read(buf, size, timeout) calls recvfrom() and logs an error - * on every timeout (EAGAIN from SO_RCVTIMEO). */ + /* --- Wait for RT thread to post new data --- + * ResetWait sleeps the background thread until the RT thread calls + * Synchronise() and posts dataSem, or until the timeout expires. + * Doing this FIRST means the thread spends nearly all its time here + * instead of spinning on the non-blocking select() below. + * Command latency is bounded by UDPS_DATA_WAIT_MS (acceptable for + * CONNECT / DISCONNECT). */ + ErrorManagement::ErrorType waitErr = + dataSem.ResetWait(TimeoutType(UDPS_DATA_WAIT_MS)); + bool dataReady = (waitErr == ErrorManagement::NoError); + + /* --- Poll server socket for incoming client commands (non-blocking) --- */ uint8 cmdBuf[256u]; Handle sockFd = serverSocket.GetReadHandle(); fd_set rfds; FD_ZERO(&rfds); FD_SET(static_cast(sockFd), &rfds); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = static_cast(UDPS_RECV_TIMEOUT_MS) * 1000L; + struct timeval tv = { 0, 0 }; /* non-blocking poll */ int nReady = select(static_cast(sockFd) + 1, &rfds, NULL_PTR(fd_set *), NULL_PTR(fd_set *), &tv); if (nReady > 0) { uint32 recvSize = static_cast(sizeof(cmdBuf)); @@ -636,12 +645,6 @@ ErrorManagement::ErrorType UDPStreamer::Execute(ExecutionInfo &info) { } } - /* --- Wait for RT thread to post new data --- */ - /* ResetWait atomically lowers the barrier then waits, preventing missed posts */ - ErrorManagement::ErrorType waitErr = - dataSem.ResetWait(TimeoutType(UDPS_DATA_WAIT_MS)); - bool dataReady = (waitErr == ErrorManagement::NoError); - if (dataReady && clientConnected) { /* Copy readyBuffer → scratchBuffer under brief spinlock */ uint64 ts = 0u; diff --git a/Test/MARTeApp/run.sh b/Test/MARTeApp/run.sh index 1e4318a..bf18da3 100755 --- a/Test/MARTeApp/run.sh +++ b/Test/MARTeApp/run.sh @@ -61,7 +61,7 @@ WEBUI_DIR="${REPO_ROOT}/Client/WebUI" WEBUI_BIN="${WEBUI_DIR}/udpstreamer-webui" if [ "${START_WEBUI}" -eq 1 ] && [ ! -x "${WEBUI_BIN}" ]; then echo "==> Building WebUI..." - (cd "${WEBUI_DIR}" && go build -o udpstreamer-webui ./...) + (cd "${WEBUI_DIR}" && rm udpstreamer-webui && go build -o udpstreamer-webui ./...) echo "==> WebUI build done." fi