Conversation
Add paths-ignore to cmake-multi-platform workflow to avoid running build and tests when only documentation files change. Keeps docs/requirements and open-someip-spec paths active to ensure ASPICE traceability scripts still run on spec/requirement changes.
Port the SOME/IP stack to Zephyr RTOS while maintaining full backward compatibility with existing macOS/Linux host builds. All 11 host tests continue to pass. Platform abstraction (include/platform/): - byteorder.h: portable htons/ntohl via someip_htons macros - net.h: portable socket includes (POSIX / Zephyr BSD sockets) - thread.h: std::thread (host) / k_thread (embedded) wrappers - memory.h: std::make_shared (host) / k_mem_slab pool (embedded) Code changes: - Remove std::regex from endpoint.cpp (manual IPv4/IPv6 parsing) - Replace direct arpa/inet.h includes with platform/byteorder.h - Replace direct POSIX socket includes with platform/net.h - Replace close()/fcntl() with portable helpers Zephyr module (zephyr/): - module.yml, CMakeLists.txt, Kconfig with per-feature toggles - Board configs: native_sim, mr_canhubk3 (S32K344), s32k388_renode - Custom board definition for S32K388 Renode simulation - Renode script with GMAC Ethernet support - Sample apps: net_test, hello_s32k, someip_echo - Test apps: test_core, test_transport Infrastructure: - Dockerfile.zephyr + docker-compose.zephyr.yml - scripts: zephyr_build.sh, run_zephyr_tests.sh, run_renode_test.sh - .github/workflows/zephyr.yml (4 CI jobs) - docs/ZEPHYR_PORT_PROGRESS.md
…phyr portability Replace all direct usage of std::thread, std::mutex, std::condition_variable, std::scoped_lock, std::lock_guard, and std::future across 19 files with portable platform:: wrappers. On host/native_sim these are transparent aliases to the std:: types; on embedded Zephyr they use k_thread/k_mutex/ k_condvar from the Zephyr kernel.
- Fix version from 0.0.1 to 0.0.2 - Update test count from 62+ to 169 C++ / 80+ Python - Add E2E Protection, configurable UDP to Core Features - Rewrite Project Structure tree to match actual filesystem - Expand Architecture section with all 8 library modules - Merge duplicated Development Status sections - Add mentions of Docker, pre-commit, Sphinx-Needs, cross-platform demo - Remove Windows/MSVC from prerequisites (CI dropped) - Fix test execution paths (./bin/test_*) - Fix CHANGELOG URLs from placeholder to vtz/opensomeip
Add paths-ignore to cmake-multi-platform workflow to avoid running build and tests when only documentation files change. Keeps docs/requirements and open-someip-spec paths active to ensure ASPICE traceability scripts still run on spec/requirement changes.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Zephyr RTOS integration and a platform abstraction layer (threading, mutexes, condition variables, sockets, byte-order, message allocation); migrates synchronization and socket code to that layer; introduces Zephyr module/Kconfig, boards, samples, tests, Renode scripts, Docker/dev images, helper scripts, CI workflow, docs, and examples. Changes
Sequence Diagram(s)sequenceDiagram
participant App as SOMEIP Module
participant Plat as someip::platform
participant RT as Runtime (Zephyr / Host)
participant Net as Network Layer
App->>Plat: start transport / create thread
Plat->>RT: create native thread (k_thread or std::thread)
RT-->>Plat: thread handle
App->>Plat: open socket / bind
Plat->>Net: socket / bind (zsock_ or POSIX)
Net-->>Plat: fd/result
App->>Plat: send message (serialize + someip_hton*)
Plat->>Net: send/sendto (someip_set_nonblocking)
Net-->>Plat: send result
Plat-->>App: receive callback (deserialize + someip_ntoh*)
App->>Plat: stop transport / close socket
Plat->>RT: join thread / cleanup
RT-->>Plat: joined
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Requirements Validation ReportRequirements Change Summary
Added Requirements
Validation Details |
There was a problem hiding this comment.
Actionable comments posted: 35
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/events/event_publisher.cpp (1)
258-275:⚠️ Potential issue | 🟠 MajorAvoid self-deadlock in publish_cyclic_events.
publish_cyclic_events()holdsevents_mutex_and then callspublish_event(), which tries to lock the same mutex again. With a non-recursive mutex, this will deadlock.🔧 Suggested fix (publish outside the lock)
void publish_cyclic_events() { - platform::ScopedLock events_lock(events_mutex_); auto now = std::chrono::steady_clock::now(); + std::vector<uint16_t> due_events; - for (auto& event_pair : registered_events_) { - const auto& config = event_pair.second; + { + platform::ScopedLock events_lock(events_mutex_); + for (auto& event_pair : registered_events_) { + const auto& config = event_pair.second; - if (config.notification_type == NotificationType::PERIODIC && - config.cycle_time.count() > 0) { + if (config.notification_type == NotificationType::PERIODIC && + config.cycle_time.count() > 0) { - auto time_since_last = std::chrono::duration_cast<std::chrono::milliseconds>( - now - last_publish_times_[config.event_id]); + auto time_since_last = std::chrono::duration_cast<std::chrono::milliseconds>( + now - last_publish_times_[config.event_id]); - if (time_since_last >= config.cycle_time) { - publish_event(config.event_id, {}); - last_publish_times_[config.event_id] = now; - } + if (time_since_last >= config.cycle_time) { + due_events.push_back(config.event_id); + last_publish_times_[config.event_id] = now; + } + } } } + + for (auto event_id : due_events) { + publish_event(event_id, {}); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/events/event_publisher.cpp` around lines 258 - 275, publish_cyclic_events currently holds events_mutex_ and calls publish_event which re-locks the same mutex causing deadlock; fix by collecting events to publish while holding events_mutex_ then releasing the lock before calling publish_event. Specifically, in publish_cyclic_events iterate registered_events_ under events_mutex_, for each periodic event whose time_since_last >= config.cycle_time push its config.event_id into a local vector (and update last_publish_times_[config.event_id] = now while still holding the lock to avoid races), then release events_mutex_ and loop over the collected event IDs calling publish_event(event_id, {}).src/tp/tp_reassembler.cpp (1)
86-99:⚠️ Potential issue | 🔴 CriticalCritical: Erase key mismatch causes resource leak in completed buffers.
The map
reassembly_buffers_is indexed bysegment.header.sequence_numberduring insertion (line 159), but erasing at line 98 usesbuffer->message_id. Since these are different fields, the erase operation will fail silently, leaving completed buffers permanently in the map. Usesegment.header.sequence_numberor store the insertion key in the buffer for consistent removal.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/tp/tp_reassembler.cpp` around lines 86 - 99, The erase uses the wrong key causing completed buffers to remain in reassembly_buffers_: when removing the finished buffer in the block that calls find_or_create_buffer, add_segment_to_buffer, is_complete and get_complete_message, ensure you erase by the same key used at insertion (the sequence key stored as segment.header.sequence_number) or make the insertion key explicit on the buffer (e.g., set buffer->map_key or assign buffer->message_id at creation) and then call reassembly_buffers_.erase(that_key); update the removal in the completion branch accordingly (references: buffers_mutex_, find_or_create_buffer, add_segment_to_buffer, reassembly_buffers_, buffer->message_id, segment.header.sequence_number, get_complete_message).src/someip/message.cpp (1)
212-232:⚠️ Potential issue | 🟠 MajorUse
std::memcpyinstead ofreinterpret_castfor safe, alignment-agnostic reads from byte buffers.The current code casts a byte buffer pointer directly to
uint32_t*and dereferences it. This can cause SIGBUS/faults on embedded architectures (ARM, MIPS, etc.) that trap unaligned memory access. Sincedatacomes from external network sources, alignment is not guaranteed.The codebase already uses
std::memcpyfor safe deserialization insrc/serialization/serializer.cpp(lines 446, 457, 468). Apply the same pattern here. Additionally, the same issue exists insrc/e2e/e2e_header.cpp(lines 63, 67, 71, 75 with bothuint32_tanduint16_t).Suggested fix (message.cpp)
- uint32_t message_id_be = *reinterpret_cast<const uint32_t*>(&data[offset]); + uint32_t message_id_be; + std::memcpy(&message_id_be, &data[offset], sizeof(message_id_be)); message_id_ = MessageId::from_uint32(someip_ntohl(message_id_be)); offset += sizeof(uint32_t); - uint32_t length_be = *reinterpret_cast<const uint32_t*>(&data[offset]); + uint32_t length_be; + std::memcpy(&length_be, &data[offset], sizeof(length_be)); length_ = someip_ntohl(length_be); offset += sizeof(uint32_t); - uint32_t request_id_be = *reinterpret_cast<const uint32_t*>(&data[offset]); + uint32_t request_id_be; + std::memcpy(&request_id_be, &data[offset], sizeof(request_id_be)); request_id_ = RequestId::from_uint32(someip_ntohl(request_id_be)); offset += sizeof(uint32_t);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/someip/message.cpp` around lines 212 - 232, Replace the unsafe unaligned reads that use reinterpret_cast in the deserialization code with alignment-agnostic std::memcpy copies from the byte buffer into local uint32_t variables before byte-order conversion; specifically, in the block that assigns message_id_ (use a local uint32_t message_id_be and memcpy from &data[offset], then call someip_ntohl and MessageId::from_uint32), similarly for length_ (local uint32_t length_be) and request_id_ (local uint32_t request_id_be then RequestId::from_uint32), and apply the same pattern in src/e2e/e2e_header.cpp for the uint32_t/uint16_t reads to avoid unaligned access on embedded targets.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/cmake-multi-platform.yml:
- Around line 7-16: Yamllint flags the branch arrays for "too many spaces inside
brackets"; update both occurrences of the branches array (the lines with
branches: [ "main" ] ) to remove inner spaces so they read branches: ["main"]
(i.e., change [ "main" ] to ["main"] for both the top-level branches and the
pull_request branches array).
In @.github/workflows/zephyr.yml:
- Around line 1-8: The workflow "Zephyr Build & Test" uses flow collections and
unquoted or poorly spaced values that trigger actionlint/yamllint; fix by
normalizing the flow lists and quoting expansions: change on.push.branches and
on.pull_request.branches to compact quoted flow lists like
["main","feature/zephyr-port"] (no extra spaces), and make paths-ignore entries
consistently quoted and compact (e.g.
['**/*.md','docs/**','LICENSE','.cursor/**']); apply the same normalized
quoting/spacing to all other flow collections and glob lists referenced (lines
affecting branches, paths-ignore, and similar keys) so linters accept the YAML.
- Around line 32-41: The workflow steps named "Build & run test_core" and "Build
& run someip_echo" currently append "|| true" to the runtime commands (the lines
starting with "timeout 30 build/.../zephyr.exe || true"), which masks failures;
remove the "|| true" from those commands so the timeout/exit status will fail
the job when the binary fails or times out (alternatively replace with explicit
error handling that exits non‑zero) to ensure test failures break the CI.
In `@Dockerfile.zephyr`:
- Around line 21-63: The image currently runs as root; create a non-root user
and switch to it after setup by adding steps to create a dedicated user (e.g.,
user "ciuser" or "zephyrci") and group, create a home directory, chown
/workspace and /opt/renode (and any other runtime dirs) to that user, and add a
final USER instruction so subsequent commands run unprivileged; ensure setup
steps that require root (apt-get, wget/tar into /opt, west init/update, make in
/workspace/zephyrproject/tools/net-tools, and any ENV exports) remain before the
USER switch and that WORKDIR /workspace/someip is owned by the new user.
In `@docs/ZEPHYR_PORT_PROGRESS.md`:
- Around line 5-7: Replace the English heading "Targets" with a Portuguese
equivalent (e.g., "Objetivos" or "Alvos") in the markdown block that currently
reads "- **Targets**: native_sim, mr_canhubk3 (S32K344), s32k388_renode
(S32K388)"; update the bold label "**Targets**" to "**Objetivos**" (or
"**Alvos**") so the document remains consistent in Portuguese while keeping the
listed targets unchanged.
- Around line 263-266: The Portuguese text uses the English word "target" in the
line "- Criado `scripts/run_zephyr_tests.sh` -- orquestra build + execucao para
cada target"; update that occurrence to a Portuguese term (e.g., "alvo" or
"objetivo") for consistency across the document—edit the string containing "para
cada target" to "para cada alvo" or "para cada objetivo" in
docs/ZEPHYR_PORT_PROGRESS.md and keep the rest of the sentence unchanged.
In `@include/platform/net.h`:
- Around line 34-86: Windows builds lack implementations of
someip_set_nonblocking and someip_set_blocking, causing undefined symbol errors;
add Windows-specific versions that use ioctlsocket(fd, FIONBIO, &mode) (with
mode = 1 for nonblocking, 0 for blocking) and return 0 on success / -1 on
failure, and include <winsock2.h> as needed, or alternatively guard call sites
in tcp_transport.cpp and udp_transport.cpp behind `#if` !defined(_WIN32) to avoid
calling those functions on Windows; implement the functions as static inline in
include/platform/net.h alongside the existing POSIX and Zephyr branches and
reference the same names someip_set_nonblocking and someip_set_blocking so
callers compile on Windows.
- Around line 62-75: The Zephyr block uses fcntl/F_GETFL/F_SETFL/O_NONBLOCK but
is missing `#include` <fcntl.h> and must be guarded by
CONFIG_NET_SOCKETS_POSIX_NAMES; update the conditional to require both
__ZEPHYR__ and CONFIG_NET_SOCKETS_POSIX_NAMES and add the <fcntl.h> include so
someip_set_nonblocking and someip_set_blocking compile. Also add a
Windows-specific stub/implementation for someip_set_nonblocking and
someip_set_blocking (guarded by the Windows macro, e.g. _WIN32) so transports
that call these functions link on Windows.
In `@include/platform/thread.h`:
- Line 45: The call to k_mutex_lock inside the lock() method ignores its return
value; capture the return (e.g., int rc = k_mutex_lock(&m_, K_FOREVER)) and add
a defensive check such as __ASSERT(rc == 0, "k_mutex_lock failed: %d", rc) (or
handle non-zero return appropriately) so failures like -EAGAIN/-EBUSY are
visible; update the lock() method to use the checked return value and assertion.
- Line 97: The defaulted Thread destructor is unsafe because it can free stack_
while the Zephyr thread is still running; change ~Thread() to check joinable()
and either call k_thread_abort(thread_) to stop the kernel thread before freeing
stack_ or assert/terminate if joinable (matching std::thread behavior). Update
the Thread::~Thread implementation (not its declaration) to use joinable(),
invoke k_thread_abort(thread_) and any needed cleanup of thread_ and stack_, or
call std::terminate/assert when a running thread is detected; ensure stack_ is
only freed after the underlying Zephyr thread will no longer access it.
- Around line 185-193: Add a direct `#include` <chrono> for the Zephyr branch and
update the template sleep_for to avoid truncation: compute the duration in a
64-bit integer (use std::chrono::duration_cast<std::chrono::milliseconds> and
store count() into int64_t), return immediately on non-positive durations, then
loop calling k_msleep in safe chunks <= INT32_MAX (cast each chunk to int32_t)
until the full interval is slept. Update references in the Zephyr branch to use
std::chrono types and mention the functions/symbols sleep_for,
std::chrono::duration_cast, std::chrono::milliseconds, and k_msleep so the
change is applied in the correct template.
- Around line 108-127: The move ctor/operator for Thread are unsafe:
Thread(Thread&&) and Thread::operator=(Thread&&) memcpy the kernel k_thread and
stack_ and pass `this` into k_thread_create so the trampoline reads a moved-from
entry_ (entry_ becomes null) and the kernel gets dangling internal pointers. Fix
by deleting the move constructor and move-assignment (make Thread non-movable),
stop copying `thread_` and `stack_`, and instead allocate the callable context
on the heap and pass that heap pointer as the trampoline argument (change
trampoline to accept and static_cast the heap context pointer and delete it
after running). Update the Thread ctor to create the heap-allocated
std::function context and call k_thread_create(&thread_, stack_, ...,
trampoline, ctx, nullptr, nullptr, ...), and remove any memcpy of
`thread_`/`stack_` and any use of `this` as the trampoline arg.
- Around line 65-67: The host build needs a thin ConditionVariable wrapper that
matches the Zephyr API so ConditionVariable::wait(Mutex&) compiles
cross-platform; implement a host-specific ConditionVariable class (mirroring the
existing Zephyr one) that holds a std::condition_variable cv_ and implements
void wait(Mutex& mtx) by constructing a std::unique_lock<std::mutex> from
mtx.native_handle() (or by locking/unlocking mtx if native_handle returns a
pointer), plus notify_one() and notify_all() methods that forward to
cv_.notify_one()/notify_all(); ensure the class name and method signatures
(ConditionVariable::wait(Mutex&), notify_one, notify_all) match the Zephyr-side
symbols so callers do not need to change.
- Around line 92-94: Replace the forbidden sizeof(stack_) usage passed into
k_thread_create: in the call that uses k_thread_create(&thread_, stack_,
sizeof(stack_), trampoline, this, nullptr, nullptr, K_PRIO_PREEMPT(7), 0,
K_NO_WAIT) change the stack size argument to K_THREAD_STACK_SIZEOF(stack_) to
use the correct usable stack bytes; while here you’re reviewing the stack object
declaration also consider replacing K_THREAD_STACK_MEMBER with
K_KERNEL_STACK_MEMBER if the stack is kernel-only. Ensure the change references
the same symbols (thread_, stack_, trampoline, k_thread_create) so only the size
expression is updated.
In `@scripts/run_zephyr_tests.sh`:
- Around line 51-58: The runtime test block currently swallows failures by using
"timeout ... || true" and always increments PASSED; remove the "|| true", run
"$build_dir/zephyr/zephyr.exe" under timeout capturing its exit status,
increment PASSED only when that exit status is zero, and otherwise print an
error and exit non‑zero (or mark failure) so failures are not masked; update the
if branch that references "$build_dir/zephyr/zephyr.exe", timeout, and the
PASSED variable accordingly.
In `@src/events/event_publisher.cpp`:
- Around line 75-80: shutdown() currently takes subscriptions_mutex_ then
events_mutex_ while publish_event() takes them in the opposite order, causing a
lock-order inversion and potential deadlock; fix by never holding both mutexes
at once (or if both are required always lock them in a single, consistent
order). Specifically, in shutdown(), publish_event(), and the other affected
block (around lines 117-130) either (a) acquire one mutex, copy the needed
container (subscriptions_ or registered_events_) into a local variable and
release the mutex before accessing the other, or (b) replace separate locks with
a single atomic acquire using std::scoped_lock(subscriptions_mutex_,
events_mutex_) with the same order everywhere; update code paths that reference
subscriptions_ and registered_events_ so they operate on the local copies or
under the consistent lock ordering to eliminate inversion.
In `@src/events/event_subscriber.cpp`:
- Around line 70-71: Add an explicit include for the thread header to avoid
relying on transitive includes: include the header that defines
platform::ScopedLock and platform::Mutex (e.g. platform/thread.h) at the top of
the file so uses of platform::ScopedLock and platform::Mutex in
event_subscriber.cpp (several places such as the subscriptions_ clear and other
lock usages) have a direct dependency; update the include list to explicitly
import that header wherever platform::ScopedLock or platform::Mutex are used.
In `@src/platform/zephyr_memory.cpp`:
- Around line 26-33: Race on slab_initialized can cause double initialization
when allocate_message() is called concurrently; make ensure_slab_init()
thread-safe by guarding the initialization with a mutex (or Zephyr
k_mutex/k_spinlock) and performing a double-checked pattern: check
slab_initialized, take the lock, check slab_initialized again, call
k_mem_slab_init(&message_slab, message_pool_buffer, sizeof(someip::Message),
CONFIG_SOMEIP_MESSAGE_POOL_SIZE) and set slab_initialized = true, then release
the lock; protect the same init path used by allocate_message() so only one
thread runs the init for message_slab/message_pool_buffer.
In `@src/rpc/rpc_client.cpp`:
- Around line 92-118: The polling loop in rpc_client.cpp can treat a
late-arriving response as success because the fixed 1ms sleep can overshoot the
deadline; update the logic around call_method_async/cancel_call to enforce the
deadline by (a) replacing the unconditional sleep with a sleep capped to the
remaining time until `deadline` (compute remaining = deadline - now and sleep
for min(1ms, remaining)), and (b) after `response_ready` is true and before
returning, re-check the current time against `deadline` (under the
`platform::ScopedLock lk(sync_mtx)` that protects `sync_resp`) and if the
response arrived after the deadline, call `cancel_call(handle)` and return a
TIMEOUT result instead of success; reference symbols: call_method_async,
cancel_call, RpcResponse, response_ready, sync_mtx, handle, deadline.
In `@src/sd/sd_message.cpp`:
- Around line 14-18: Add a direct include of platform/net.h to
src/sd/sd_message.cpp so the declarations for inet_pton, inet_ntop,
INET_ADDRSTRLEN and in_addr are provided for the IPv4EndpointOption
implementation; do not rely on transitive inclusion from
platform/byteorder.h—open sd_message.cpp and insert `#include` "platform/net.h"
alongside the other includes so IPv4EndpointOption (the code using
inet_pton/inet_ntop, INET_ADDRSTRLEN, in_addr) has portable network headers
available.
In `@src/transport/endpoint.cpp`:
- Around line 188-228: The IPv6 validation loop currently treats empty segments
as acceptable whenever "::" exists, allowing invalid addresses like "1:::2" or
"1::2:3:". Update the validation so that empty segments (len == 0) are only
allowed exactly once and only at the position of the single "::" (use
double_colon/has_double_colon to check), and otherwise return false; also reject
a single leading or trailing ':' when there is no "::" (i.e., if address.front()
== ':' or address.back() == ':' and !has_double_colon return false). In the
splitting loop, when len == 0 ensure pos == double_colon and do not increment
groups for that empty segment (or track that compression was used) so the final
groups check (groups <= 7 when has_double_colon, groups == 8 otherwise) remains
correct.
- Around line 15-18: The file uses std::isdigit and std::isxdigit in the
IPv4/IPv6 validation logic but does not include the <cctype> header; add
`#include` <cctype> alongside the existing includes (near <cstring> in the header
block) so validateIPv4/validateIPv6 (or any functions that call
std::isdigit/std::isxdigit) compile correctly on strict toolchains.
In `@src/transport/tcp_transport.cpp`:
- Around line 207-212: The code currently calls
someip_set_blocking(listen_socket_fd_), then accept(...), then
someip_set_nonblocking(listen_socket_fd_) without checking return values; if
someip_set_nonblocking fails the listen socket will remain blocking and can
stall the loop. Update the sequence around someip_set_blocking, accept and
someip_set_nonblocking to check and handle errors: verify return values from
both someip_set_blocking and someip_set_nonblocking, if someip_set_nonblocking
fails after accept then close the newly accepted client_fd (if valid), attempt
to restore the listen socket to its previous mode (or log and propagate the
error), and propagate/return an error upstream so the caller can handle the
failure; reference the functions someip_set_blocking, someip_set_nonblocking and
the variables listen_socket_fd_ and client_fd to locate and modify the logic.
In `@zephyr/boards/s32k388_renode/s32k388_renode.conf`:
- Around line 1-11: The configuration enables IPv4/UDP and POSIX sockets for
SOME/IP but does not account for Service Discovery (SD) opening both multicast
and unicast sockets, so verify that CONFIG_NET_MAX_CONTEXTS is large enough to
accommodate SD plus any application sockets; if not, increase
CONFIG_NET_MAX_CONTEXTS (or document required minimum) so SD (multicast +
unicast) and your app sockets won’t exhaust contexts—check where
CONFIG_NET_MAX_CONTEXTS is defined and adjust accordingly.
In `@zephyr/Kconfig`:
- Around line 16-59: SOME/IP features SOMEIP_RPC, SOMEIP_EVENTS, and SOMEIP_TP
can be enabled without any transport which yields invalid configs; add a
dependency to each so they require at least one transport: update the Kconfig
entries for SOMEIP_RPC, SOMEIP_EVENTS, and SOMEIP_TP to include a "depends on
SOMEIP_TRANSPORT_UDP || SOMEIP_TRANSPORT_TCP" line (mirroring the existing
SOMEIP_SD pattern) so these symbols only build when either SOMEIP_TRANSPORT_UDP
or SOMEIP_TRANSPORT_TCP is enabled.
- Around line 7-13: The Kconfig menuconfig SOMEIP currently sets default y which
enables the SOME/IP protocol stack by default; change its default to n so it is
opt-in (update the menuconfig SOMEIP entry to use "default n" instead of
"default y"), keep the existing "depends on CPP" and help text intact, and
ensure no other logic relies on an implicit default-by-presence of CONFIG_SOMEIP
so that projects explicitly enable SOMEIP in prj.conf or board configs when
needed.
- Around line 61-90: Add explicit range constraints to each integer Kconfig to
prevent zero/negative and out-of-range values: add a "range 512 65536" (or
similar conservative lower/upper bounds) to SOMEIP_THREAD_STACK_SIZE, "range 1
1024" to SOMEIP_MESSAGE_POOL_SIZE, "range 1 65535" to SOMEIP_MAX_PAYLOAD_SIZE,
"range 1 255" to SOMEIP_MAX_SUBSCRIPTIONS, and "range 1 255" to
SOMEIP_MAX_PENDING_CALLS so the build-time allocations
(SOMEIP_THREAD_STACK_SIZE, SOMEIP_MESSAGE_POOL_SIZE) cannot be set to 0 and the
other placeholders have safe min/max limits.
In `@zephyr/samples/hello_s32k/src/main.cpp`:
- Around line 7-10: The file uses uint8_t (in main.cpp around the code that
declares or handles that type) but does not include <cstdint>; add an `#include`
<cstdint> to the top-of-file includes (alongside <cstdio>, <string>, <vector>,
<memory>) so that uint8_t is defined for stricter toolchains and the code using
uint8_t compiles reliably.
In `@zephyr/samples/someip_echo/CMakeLists.txt`:
- Around line 1-10: The CMakeLists sets ZEPHYR_EXTRA_MODULES after
find_package(Zephyr), so the SOMEIP module (SOMEIP_ROOT) won't be discovered;
move the block that defines SOMEIP_ROOT and appends it to ZEPHYR_EXTRA_MODULES
so it appears before the call to find_package(Zephyr). Specifically, ensure the
lines that set SOMEIP_ROOT and list(APPEND ZEPHYR_EXTRA_MODULES ${SOMEIP_ROOT})
are moved above the find_package(Zephyr REQUIRED ...) invocation (do the same
change in the other affected CMakeLists where ZEPHYR_EXTRA_MODULES is appended
after find_package).
In `@zephyr/samples/someip_echo/src/main.cpp`:
- Around line 42-63: The demo currently always returns 0 even when
deserialization or the round-trip match fails; update main so that if
decoded.deserialize(serialized) returns false OR the round-trip comparison
(match computed from decoded.get_service_id(), decoded.get_method_id(),
decoded.get_payload() vs msg) is false, main returns a non-zero exit code (e.g.,
return 1) instead of continuing to exit 0; also consider returning non-zero if
Endpoint ep.is_valid() is false to surface networking/setup problems. Use the
existing symbols decoded.deserialize(...), the 'match' boolean, and
Endpoint::is_valid()/ep to locate the spots to change.
In `@zephyr/tests/test_core/CMakeLists.txt`:
- Around line 1-9: The Zephyr module path is being appended to
ZEPHYR_EXTRA_MODULES after calling find_package(Zephyr), which prevents Zephyr
from discovering the SOME/IP module; move the list(APPEND ZEPHYR_EXTRA_MODULES
${SOMEIP_ROOT}) (and the set(SOMEIP_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../..)
that defines it) so they occur before the find_package(Zephyr REQUIRED HINTS
$ENV{ZEPHYR_BASE}) line (or use EXTRA_ZEPHYR_MODULES instead) to ensure the
module is visible during find_package.
In `@zephyr/tests/test_core/src/main.cpp`:
- Around line 100-116: Update the test to use the current
Serializer/Deserializer API: replace
Serializer::write_uint8/write_uint16/write_uint32 with
serialize_uint8/serialize_uint16/serialize_uint32 and replace get_data() with
get_buffer(); use
Deserializer::deserialize_uint8/deserialize_uint16/deserialize_uint32 which
return DeserializationResult<T> (check result.has_value() and access the value
via result.value() or equivalent) and adjust the CHECKs to validate has_value()
and the extracted value; reference symbols: Serializer, serialize_uint8,
serialize_uint16, serialize_uint32, get_buffer, Deserializer, deserialize_uint8,
deserialize_uint16, deserialize_uint32, DeserializationResult.
In `@zephyr/tests/test_transport/CMakeLists.txt`:
- Around line 1-9: The CMakeLists.txt sets ZEPHYR_EXTRA_MODULES after
find_package(Zephyr), preventing Zephyr from discovering the SOMEIP module; move
the list(APPEND ZEPHYR_EXTRA_MODULES ${SOMEIP_ROOT}) (and the set(SOMEIP_ROOT
...) that it depends on) to before the find_package(Zephyr REQUIRED ...) call so
the Zephyr package can register the extra module; apply the same reordering to
other Zephyr test/sample CMakeLists.txt files (look for ZEPHYR_EXTRA_MODULES,
find_package(Zephyr), set(SOMEIP_ROOT), and project(test_transport) to locate
affected files).
In `@zephyr/tests/test_transport/src/main.cpp`:
- Around line 48-75: The test currently lacks robust error handling and a
bounded wait for reception; add explicit checks of the Result returned by
UdpTransport::start() for both server and client and after
UdpTransport::send_message() (use the same CHECK or assert-style failure used
elsewhere), and replace the single immediate call to server.receive_message()
with a short, bounded wait loop (e.g., poll receive_message() with a timeout of
a few hundred milliseconds and a small sleep between polls) so the test fails
fast if no message arrives; reference UdpTransport::start,
UdpTransport::send_message, UdpTransport::receive_message, and
server.get_local_endpoint to locate the changes.
- Around line 47-66: The test uses hard-coded "127.0.0.1" for Endpoint
construction which fails on native_sim without loopback; either enable loopback
in project config or change the test to use the configured IPv4 address (e.g.
"192.0.2.1"). Fix by one of two actions: (A) add CONFIG_NET_LOOPBACK=y to
prj.conf so Endpoint("127.0.0.1", ...) works, or (B) modify the test where
Endpoint server_ep(...) and Endpoint client_ep(...) are constructed to use the
configured address (replace "127.0.0.1" with the configured IPv4 string such as
"192.0.2.1") so UdpTransport/ server.start() and client.start() communicate over
the TAP network.
---
Outside diff comments:
In `@src/events/event_publisher.cpp`:
- Around line 258-275: publish_cyclic_events currently holds events_mutex_ and
calls publish_event which re-locks the same mutex causing deadlock; fix by
collecting events to publish while holding events_mutex_ then releasing the lock
before calling publish_event. Specifically, in publish_cyclic_events iterate
registered_events_ under events_mutex_, for each periodic event whose
time_since_last >= config.cycle_time push its config.event_id into a local
vector (and update last_publish_times_[config.event_id] = now while still
holding the lock to avoid races), then release events_mutex_ and loop over the
collected event IDs calling publish_event(event_id, {}).
In `@src/someip/message.cpp`:
- Around line 212-232: Replace the unsafe unaligned reads that use
reinterpret_cast in the deserialization code with alignment-agnostic std::memcpy
copies from the byte buffer into local uint32_t variables before byte-order
conversion; specifically, in the block that assigns message_id_ (use a local
uint32_t message_id_be and memcpy from &data[offset], then call someip_ntohl and
MessageId::from_uint32), similarly for length_ (local uint32_t length_be) and
request_id_ (local uint32_t request_id_be then RequestId::from_uint32), and
apply the same pattern in src/e2e/e2e_header.cpp for the uint32_t/uint16_t reads
to avoid unaligned access on embedded targets.
In `@src/tp/tp_reassembler.cpp`:
- Around line 86-99: The erase uses the wrong key causing completed buffers to
remain in reassembly_buffers_: when removing the finished buffer in the block
that calls find_or_create_buffer, add_segment_to_buffer, is_complete and
get_complete_message, ensure you erase by the same key used at insertion (the
sequence key stored as segment.header.sequence_number) or make the insertion key
explicit on the buffer (e.g., set buffer->map_key or assign buffer->message_id
at creation) and then call reassembly_buffers_.erase(that_key); update the
removal in the completion branch accordingly (references: buffers_mutex_,
find_or_create_buffer, add_segment_to_buffer, reassembly_buffers_,
buffer->message_id, segment.header.sequence_number, get_complete_message).
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (65)
.github/workflows/cmake-multi-platform.yml.github/workflows/zephyr.ymlDockerfile.zephyrdocker-compose.zephyr.ymldocs/ZEPHYR_PORT_PROGRESS.mdinclude/core/session_manager.hinclude/e2e/e2e_profile_registry.hinclude/platform/byteorder.hinclude/platform/memory.hinclude/platform/net.hinclude/platform/thread.hinclude/tp/tp_manager.hinclude/tp/tp_reassembler.hinclude/transport/tcp_transport.hinclude/transport/udp_transport.hscripts/run_renode_test.shscripts/run_zephyr_tests.shscripts/zephyr_build.shsrc/core/session_manager.cppsrc/e2e/e2e_header.cppsrc/e2e/e2e_profile_registry.cppsrc/e2e/e2e_profiles/standard_profile.cppsrc/events/event_publisher.cppsrc/events/event_subscriber.cppsrc/platform/zephyr_memory.cppsrc/platform/zephyr_thread.cppsrc/rpc/rpc_client.cppsrc/rpc/rpc_server.cppsrc/sd/sd_client.cppsrc/sd/sd_message.cppsrc/sd/sd_server.cppsrc/serialization/serializer.cppsrc/someip/message.cppsrc/tp/tp_manager.cppsrc/tp/tp_reassembler.cppsrc/transport/endpoint.cppsrc/transport/tcp_transport.cppsrc/transport/udp_transport.cpptests/test_sd.cppzephyr/CMakeLists.txtzephyr/Kconfigzephyr/boards/mr_canhubk3.confzephyr/boards/native_sim.confzephyr/boards/s32k388_renode/board.ymlzephyr/boards/s32k388_renode/s32k388_renode.confzephyr/boards/s32k388_renode/s32k388_renode.dtszephyr/boards/s32k388_renode/s32k388_renode_defconfigzephyr/module.ymlzephyr/prj.confzephyr/renode/s32k388_someip.resczephyr/samples/hello_s32k/CMakeLists.txtzephyr/samples/hello_s32k/prj.confzephyr/samples/hello_s32k/src/main.cppzephyr/samples/net_test/CMakeLists.txtzephyr/samples/net_test/prj.confzephyr/samples/net_test/src/main.cppzephyr/samples/someip_echo/CMakeLists.txtzephyr/samples/someip_echo/prj.confzephyr/samples/someip_echo/src/main.cppzephyr/tests/test_core/CMakeLists.txtzephyr/tests/test_core/prj.confzephyr/tests/test_core/src/main.cppzephyr/tests/test_transport/CMakeLists.txtzephyr/tests/test_transport/prj.confzephyr/tests/test_transport/src/main.cpp
docs/ZEPHYR_PORT_PROGRESS.md
Outdated
| - **Branch**: `feature/zephyr-port` | ||
| - **Targets**: native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388) | ||
| - **Status geral**: Implementacao completa -- aguardando validacao em Docker/Zephyr |
There was a problem hiding this comment.
Substituir “Targets” por termo em português.
O documento está em português; prefira “Objetivos”/“Alvos” para consistência.
✏️ Sugestão
-- **Targets**: native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388)
+- **Objetivos**: native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - **Branch**: `feature/zephyr-port` | |
| - **Targets**: native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388) | |
| - **Status geral**: Implementacao completa -- aguardando validacao em Docker/Zephyr | |
| - **Branch**: `feature/zephyr-port` | |
| - **Objetivos**: native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388) | |
| - **Status geral**: Implementacao completa -- aguardando validacao em Docker/Zephyr |
🧰 Tools
🪛 LanguageTool
[locale-violation] ~6-~6: “Targets” é um estrangeirismo. É preferível dizer “objetivos” ou “alvos”.
Context: ...- Branch: feature/zephyr-port - Targets: native_sim, mr_canhubk3 (S32K344), s...
(PT_BARBARISMS_REPLACE_TARGETS)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/ZEPHYR_PORT_PROGRESS.md` around lines 5 - 7, Replace the English heading
"Targets" with a Portuguese equivalent (e.g., "Objetivos" or "Alvos") in the
markdown block that currently reads "- **Targets**: native_sim, mr_canhubk3
(S32K344), s32k388_renode (S32K388)"; update the bold label "**Targets**" to
"**Objetivos**" (or "**Alvos**") so the document remains consistent in
Portuguese while keeping the listed targets unchanged.
Zephyr 4.3.x requires jsonschema at configure time but the CI container image (ci:v0.27.4) does not ship it.
There was a problem hiding this comment.
Actionable comments posted: 18
♻️ Duplicate comments (2)
.github/workflows/zephyr.yml (2)
33-42:⚠️ Potential issue | 🟠 MajorTest failures are silently swallowed by
|| true.Both
timeoutcommands on lines 37 and 42 append|| true, so the job always succeeds regardless of test outcome. This makes the native_sim CI job unreliable.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 33 - 42, The test steps "Build & run test_core" and "Build & run someip_echo" are masking failures by appending "|| true" to the timeout invocations; remove the "|| true" suffix from the two commands (the lines starting with "timeout 30 build/ns_tc/zephyr/zephyr.exe || true" and "timeout 30 build/ns_echo/zephyr/zephyr.exe || true") so the step will fail on non‑zero exit and the workflow will correctly report test failures.
70-75:⚠️ Potential issue | 🟡 MinorQuote
$GITHUB_WORKSPACEto prevent word splitting.Shellcheck SC2086 flags the unquoted expansion on line 75. If the path ever contains spaces, the build will break.
🔧 Proposed fix
west build -b s32k388_renode zephyr/samples/hello_s32k \ -d build/s32k388 --pristine auto -- \ - -DBOARD_ROOT=$GITHUB_WORKSPACE/zephyr/boards + -DBOARD_ROOT="$GITHUB_WORKSPACE/zephyr/boards"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 70 - 75, The -DBOARD_ROOT argument in the GitHub Actions workflow step "Build hello_s32k (s32k388_renode)" uses an unquoted variable expansion ($GITHUB_WORKSPACE) which can break if the path contains spaces; update the run command to quote the expansion so the option becomes -DBOARD_ROOT="$GITHUB_WORKSPACE/zephyr/boards" (keep the rest of the west build invocation unchanged).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/cmake-multi-platform.yml:
- Around line 8-29: The workflow file contains unresolved Git conflict markers
(<<<<<<<, =======, >>>>>>>) inside the paths-ignore lists causing invalid YAML;
remove the conflict markers and consolidate the intended entries by keeping the
'open-someip-spec/**' exclusion in both the top-level "paths-ignore" and the
"pull_request.paths-ignore" blocks so that the final lists are valid YAML arrays
without any conflict markers (locate the lists around the "paths-ignore" keys
and update them in-place).
In @.github/workflows/zephyr.yml:
- Around line 28-32: The "Init Zephyr" step is duplicated; extract those
commands into a reusable composite action and replace the inline step with a
single call to that action. Create a composite action that runs the pip install
jsonschema and the three west commands (west init /tmp/zp && cd /tmp/zp; west
update --narrow -o=--depth=1; west zephyr-export), publish it in
.github/actions/zephyr-init (or similar), and update each job's step named "Init
Zephyr" to use uses: ./.github/actions/zephyr-init (or the repository/action
reference) so all jobs call the same composite action.
In `@docker-compose.dev.yml`:
- Around line 7-18: The dev service in docker-compose.dev.yml (service name
"dev", Dockerfile "Dockerfile.dev") lacks network_mode: host required for Zephyr
native_sim networking; add network_mode: host under the dev service to allow
access to host network interfaces for UDP/multicast tests (or alternatively add
a clarifying comment that network configuration is provided by a separate
compose file such as docker-compose.zephyr.yml if you intend to keep this file
unchanged).
In `@Dockerfile.dev`:
- Around line 40-42: The RUN pip3 install line in Dockerfile.dev installs many
unpinned packages (west, pyelftools, pyyaml, pykwalify, packaging, canopen,
jsonschema, pytest, pytest-cov, coverage, junit-xml) which risks
non-reproducible/breaking builds; fix this by either creating a requirements.txt
that pins exact versions for each listed package and updating the Dockerfile.dev
RUN to pip3 install --no-cache-dir -r requirements.txt, or pin each package
inline with specific version specifiers (e.g., package==x.y.z) while keeping
--no-cache-dir; ensure the chosen versions are tested and committed alongside
the Dockerfile.dev.
- Around line 44-54: The case and subsequent RUN expansions use unquoted shell
variables (HOSTARCH and SDKARCH), which can trigger shellcheck SC2086; update
the Dockerfile RUN block to quote the variables everywhere they are expanded
(e.g., use "case \"$HOSTARCH\" in" and use "${SDKARCH}" in the wget/tar
filenames and any other expansions) so the case statement, wget URL, tar
extraction and cleanup use quoted variable expansions consistently.
In `@examples/basic/sd_demo/server.cpp`:
- Around line 62-67: The call to transport_->send_message(response, sender)
ignores its return value so send failures are silent; update the handler to
capture the result of send_message (from transport_->send_message) and on
non-success log a clear error including identifying details (e.g., sender,
MessageId/METHOD_HELLO, RequestId) and optionally return or retry; locate this
in server.cpp around the response construction where response is created and
sent and add error handling/logging for the send_message result.
- Around line 40-42: Replace the non-guaranteed signal-safe atomic with a
signal-safe flag: change the global variable named running (currently declared
as std::atomic<bool>) to a volatile std::sig_atomic_t and update signal_handler
(static void signal_handler(int)) to assign 0/1 to that flag; also update any
checks of running elsewhere in the code to test against 0/1. Ensure <csignal> is
included if not already.
In `@README.md`:
- Around line 63-66: Update the prerequisites section in README.md to clarify
platform/toolchain differences: modify the bullet list under the "Prerequisites"
heading to state that a POSIX-compatible system (Linux, macOS) and
C++17-compatible compiler/CMake are required for native/host builds and tests,
and add a separate note that Zephyr builds use the Zephyr toolchain/environment
(so non-POSIX targets are supported via Zephyr). Ensure the wording replaces the
existing POSIX-only line and adds an explicit Zephyr build/toolchain note so
readers understand both workflows.
In `@scripts/run_client_server_test.sh`:
- Around line 43-51: The current test success criteria treat exit codes 124
(timeout) and 137 (SIGKILL) as success, which is misleading since these indicate
abnormal termination. Update the conditional in the script to only treat exit
code 0 as success. If you intentionally want to keep 124 and 137 as accepted
codes due to specific process cleanup reasons, add a clear comment above this
conditional explaining why these codes are considered successful to aid future
maintainers.
- Around line 35-43: The timeout command currently has "|| true", which masks
its real exit code so CLIENT_EXIT is always 0; remove "|| true" from the timeout
invocation (keep the timeout 15 "$BUILD_CLIENT/zephyr/zephyr.exe" invocation
as-is) and then immediately capture its exit status into CLIENT_EXIT
(CLIENT_EXIT=$?) so the subsequent conditional correctly checks real exit codes
(e.g., 0, 124, 137); keep the server shutdown lines (kill "$SERVER_PID"
2>/dev/null || true and wait "$SERVER_PID" 2>/dev/null || true) so the script
still cleans up even when the client process fails.
In `@scripts/run_sd_demo.sh`:
- Around line 32-34: The script sets CLIENT_EXIT after running the timeout
command but uses "|| true", which masks the real exit status; remove the "||
true" so the timeout invocation (timeout 30
"$PROJECT_DIR/build/zephyr/native_sim_sd_client/zephyr/zephyr.exe") returns its
actual exit code and CLIENT_EXIT captures it correctly; also ensure any cleanup
or conditional logic that previously relied on forced success still handles
non-zero CLIENT_EXIT values as intended.
- Around line 8-22: The script currently uses "set -e" which doesn't make
pipelines fail when a command like the cmake or west build (the cmake --build
and west build pipelines that end with | tail -3) fails; update the script
startup to enable pipefail (e.g., replace or augment the existing set -e with a
pipefail-enabled setting such as set -o pipefail or set -eo pipefail, or set
-euo pipefail) so failures inside the cmake --build and west build pipelines
propagate and cause the script to exit.
In `@zephyr/samples/someip_client/src/main.cpp`:
- Around line 37-71: The current send_and_receive accepts any response matching
SERVICE_ID/METHOD_HELLO and RESPONSE type, which can return unrelated or delayed
replies; update the response check in send_and_receive to also validate the
request/session identifiers (compare reply->get_request_id() or
reply->get_request_id().get_session_id() against the RequestId created for the
request and the session_id argument) and, if your Message API exposes a client
ID, also verify the client ID matches the one used in the original RequestId so
only responses for the same session/client are accepted.
In `@zephyr/samples/someip_sd_client/prj.conf`:
- Around line 18-25: The prj.conf enables CONFIG_SOMEIP_E2E though the SD client
code does not implement E2E protection; change CONFIG_SOMEIP_E2E from y to n (or
remove it) to avoid pulling in unused E2E code and reduce build size; also check
whether CONFIG_NET_SOCKETS_POSIX_NAMES is required by this sample (compare
behavior with someip_echo) and remove or disable that CONFIG if it is not
actually used by the someip_sd client to keep configuration consistent with
other someip_client/server samples.
In `@zephyr/samples/someip_sd_client/src/main.cpp`:
- Around line 37-51: The on_found callback writes disc_address and disc_port
while main reads them, which can race if on_found runs again; protect the shared
state by adding a synchronization primitive (e.g., a std::mutex sd_mutex) and
lock it around all writes in on_found (when setting disc_address, disc_port and
discovered) and around reads in main (or copy the values under the lock and
release before use); alternatively encapsulate address/port/discovered into a
single struct and guard it with the same mutex to ensure atomic updates and safe
reads.
In `@zephyr/samples/someip_server/prj.conf`:
- Around line 16-23: The prj.conf currently sets CONFIG_SOMEIP_E2E=y while this
sample doesn’t use E2E features; if you intend this sample to be a minimal demo
like someip_echo, change CONFIG_SOMEIP_E2E to n in prj.conf (modify the
CONFIG_SOMEIP_E2E entry) and add a short inline comment explaining it’s disabled
for minimal behavior, otherwise leave CONFIG_SOMEIP_E2E=y to follow the standard
SOME/IP sample defaults.
In `@zephyr/samples/someip_server/src/main.cpp`:
- Around line 7-13: The file-level comment incorrectly says the server listens
on 127.0.0.1:30490 while the code constructs an Endpoint with "0.0.0.0" (all
interfaces) in main (Endpoint at the top-level/constructor); update the comment
to state the server listens on 0.0.0.0:30490 (or alternatively change the
Endpoint construction to "127.0.0.1" if you intend loopback-only) so the
documentation matches the implementation, referencing the Endpoint usage in
main.cpp.
- Around line 109-113: The final `return 0;` in main is unreachable because of
the infinite `while (true)` loop; remove the dead `return 0;` or restructure the
`while (true)` in main (e.g., make it conditional or break on a shutdown
condition) so the function can terminate cleanly and eliminate the compiler
warning; locate the infinite loop and the trailing `return 0;` in main.cpp to
apply the change.
---
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 33-42: The test steps "Build & run test_core" and "Build & run
someip_echo" are masking failures by appending "|| true" to the timeout
invocations; remove the "|| true" suffix from the two commands (the lines
starting with "timeout 30 build/ns_tc/zephyr/zephyr.exe || true" and "timeout 30
build/ns_echo/zephyr/zephyr.exe || true") so the step will fail on non‑zero exit
and the workflow will correctly report test failures.
- Around line 70-75: The -DBOARD_ROOT argument in the GitHub Actions workflow
step "Build hello_s32k (s32k388_renode)" uses an unquoted variable expansion
($GITHUB_WORKSPACE) which can break if the path contains spaces; update the run
command to quote the expansion so the option becomes
-DBOARD_ROOT="$GITHUB_WORKSPACE/zephyr/boards" (keep the rest of the west build
invocation unchanged).
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (20)
.github/workflows/cmake-multi-platform.yml.github/workflows/zephyr.ymlCHANGELOG.mdDockerfile.devREADME.mddocker-compose.dev.ymlexamples/CMakeLists.txtexamples/basic/sd_demo/CMakeLists.txtexamples/basic/sd_demo/server.cppscripts/run_client_server_test.shscripts/run_sd_demo.shzephyr/samples/someip_client/CMakeLists.txtzephyr/samples/someip_client/prj.confzephyr/samples/someip_client/src/main.cppzephyr/samples/someip_sd_client/CMakeLists.txtzephyr/samples/someip_sd_client/prj.confzephyr/samples/someip_sd_client/src/main.cppzephyr/samples/someip_server/CMakeLists.txtzephyr/samples/someip_server/prj.confzephyr/samples/someip_server/src/main.cpp
| CONFIG_SOMEIP=y | ||
| CONFIG_SOMEIP_TRANSPORT_UDP=y | ||
| CONFIG_SOMEIP_TRANSPORT_TCP=n | ||
| CONFIG_SOMEIP_SD=y | ||
| CONFIG_SOMEIP_RPC=n | ||
| CONFIG_SOMEIP_EVENTS=n | ||
| CONFIG_SOMEIP_E2E=y | ||
| CONFIG_SOMEIP_TP=n |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if other Zephyr sample prj.conf files enable NET_SOCKETS_POSIX_NAMES
echo "=== Checking NET_SOCKETS_POSIX_NAMES in other samples ==="
fd -t f 'prj.conf' zephyr/samples --exec grep -l 'NET_SOCKETS_POSIX_NAMES' {} \;
echo ""
echo "=== Checking all CONFIG settings in other SOMEIP samples ==="
fd -t f 'prj.conf' zephyr/samples/someipRepository: vtz/opensomeip
Length of output: 372
🏁 Script executed:
#!/bin/bash
# Check if transport code uses POSIX socket calls that need the mapping
echo "=== Checking POSIX socket calls in transport code ==="
rg -n 'socket\(|bind\(|sendto\(|recvfrom\(|close\(' --type cpp -g '!test*' src/transport/ | head -50
echo ""
echo "=== Check if E2E is used in the SD client sample ==="
rg -n 'E2E|e2e' zephyr/samples/someip_sd_client/src/Repository: vtz/opensomeip
Length of output: 2017
🏁 Script executed:
#!/bin/bash
# Compare prj.conf files across all someip samples
echo "=== Full prj.conf for someip_sd_client ==="
cat zephyr/samples/someip_sd_client/prj.conf
echo ""
echo "=== List all someip samples ==="
fd -t d . zephyr/samples -d 1 | grep someipRepository: vtz/opensomeip
Length of output: 739
🏁 Script executed:
#!/bin/bash
echo "=== someip_echo/prj.conf ==="
cat zephyr/samples/someip_echo/prj.conf
echo ""
echo "=== net_test/prj.conf ==="
cat zephyr/samples/net_test/prj.confRepository: vtz/opensomeip
Length of output: 1334
🏁 Script executed:
#!/bin/bash
# Check if CONFIG_POSIX_API enables NET_SOCKETS_POSIX_NAMES implicitly
# or if they are independent configs
echo "=== Searching for NET_SOCKETS_POSIX_NAMES definition in Kconfig ==="
rg -n 'NET_SOCKETS_POSIX_NAMES' --type kconfig | head -20
echo ""
echo "=== Checking main.cpp to see what socket APIs are actually called ==="
cat zephyr/samples/someip_sd_client/src/main.cpp | head -100Repository: vtz/opensomeip
Length of output: 3408
🏁 Script executed:
#!/bin/bash
echo "=== Searching for NET_SOCKETS_POSIX_NAMES in all config files ==="
rg -n 'NET_SOCKETS_POSIX_NAMES' -t conf
echo ""
echo "=== Check other SOMEIP sample configs for comparison ==="
for f in zephyr/samples/someip_*/prj.conf; do
echo "=== $f ==="
grep -E 'POSIX|E2E' "$f" || echo "(no matches)"
doneRepository: vtz/opensomeip
Length of output: 601
🏁 Script executed:
#!/bin/bash
echo "=== Checking if someip_echo and net_test have anything else in common ==="
echo "net_test has NET_SOCKETS_POSIX_NAMES:"
grep 'NET_SOCKETS_POSIX_NAMES' zephyr/samples/net_test/prj.conf
echo ""
echo "someip_echo has NET_SOCKETS_POSIX_NAMES:"
grep 'NET_SOCKETS_POSIX_NAMES' zephyr/samples/someip_echo/prj.conf
echo ""
echo "All SOMEIP samples:"
for f in zephyr/samples/someip_*/prj.conf; do
echo "=== $(basename $(dirname $f)) ==="
grep -E 'CONFIG_SOMEIP_E2E|CONFIG_NET_SOCKETS_POSIX_NAMES|CONFIG_POSIX_API' "$f"
doneRepository: vtz/opensomeip
Length of output: 576
Remove CONFIG_SOMEIP_E2E=y — it is unused in this sample.
The SD client code does not implement E2E protection. Set CONFIG_SOMEIP_E2E=n to reduce build footprint, consistent with the pattern in someip_echo/prj.conf.
Regarding CONFIG_NET_SOCKETS_POSIX_NAMES: Only someip_echo among the SOMEIP samples enables it; someip_client and someip_server do not. Verify whether this is needed here or if it is specific to the echo sample.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/someip_sd_client/prj.conf` around lines 18 - 25, The prj.conf
enables CONFIG_SOMEIP_E2E though the SD client code does not implement E2E
protection; change CONFIG_SOMEIP_E2E from y to n (or remove it) to avoid pulling
in unused E2E code and reduce build size; also check whether
CONFIG_NET_SOCKETS_POSIX_NAMES is required by this sample (compare behavior with
someip_echo) and remove or disable that CONFIG if it is not actually used by the
someip_sd client to keep configuration consistent with other
someip_client/server samples.
| static std::atomic<bool> discovered{false}; | ||
| static std::string disc_address; | ||
| static uint16_t disc_port = 0; | ||
|
|
||
| static void on_found(const std::vector<ServiceInstance>& services) { | ||
| for (auto& svc : services) { | ||
| if (svc.service_id == SERVICE_ID && !svc.ip_address.empty() && svc.port != 0) { | ||
| disc_address = svc.ip_address; | ||
| disc_port = svc.port; | ||
| discovered = true; | ||
| printf("[sd] Discovered service 0x%04X at %s:%d\n", | ||
| svc.service_id, svc.ip_address.c_str(), svc.port); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Data race on disc_address / disc_port — currently safe but fragile.
disc_address (std::string) and disc_port are written in the on_found callback (likely invoked from the SD client's background thread) and read in main. The sequential-consistency ordering on discovered does establish the correct happens-before relationship for a single writer → single reader pattern, so this works today.
However, if on_found is ever invoked a second time after discovered is already true, disc_address could be mutated while main is reading it. Consider using a mutex or consolidating into a single atomic/protected struct to make the intent explicit and guard against future changes.
🛡️ Suggested improvement
+#include <mutex>
+
+static std::mutex disc_mutex;
static std::atomic<bool> discovered{false};
static std::string disc_address;
static uint16_t disc_port = 0;
static void on_found(const std::vector<ServiceInstance>& services) {
for (auto& svc : services) {
if (svc.service_id == SERVICE_ID && !svc.ip_address.empty() && svc.port != 0) {
+ std::lock_guard<std::mutex> lk(disc_mutex);
+ if (discovered) return; // first discovery wins
disc_address = svc.ip_address;
disc_port = svc.port;
discovered = true;🧰 Tools
🪛 Cppcheck (2.19.0)
[information] 42-42: Include file
(missingIncludeSystem)
[information] 43-43: Include file
(missingIncludeSystem)
[information] 44-44: Include file
(missingIncludeSystem)
[information] 45-45: Include file
(missingIncludeSystem)
[information] 46-46: Include file
(missingIncludeSystem)
[information] 47-47: Include file
(missingIncludeSystem)
[information] 48-48: Include file
(missingIncludeSystem)
[information] 37-37: Include file
(missingIncludeSystem)
[style] 47-47: The function 'try_lock' is never used.
(unusedFunction)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/someip_sd_client/src/main.cpp` around lines 37 - 51, The
on_found callback writes disc_address and disc_port while main reads them, which
can race if on_found runs again; protect the shared state by adding a
synchronization primitive (e.g., a std::mutex sd_mutex) and lock it around all
writes in on_found (when setting disc_address, disc_port and discovered) and
around reads in main (or copy the values under the lock and release before use);
alternatively encapsulate address/port/discovered into a single struct and guard
it with the same mutex to ensure atomic updates and safe reads.
| CONFIG_SOMEIP=y | ||
| CONFIG_SOMEIP_TRANSPORT_UDP=y | ||
| CONFIG_SOMEIP_TRANSPORT_TCP=n | ||
| CONFIG_SOMEIP_SD=n | ||
| CONFIG_SOMEIP_RPC=n | ||
| CONFIG_SOMEIP_EVENTS=n | ||
| CONFIG_SOMEIP_E2E=y | ||
| CONFIG_SOMEIP_TP=n |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
# Find the prj.conf and main.cpp files in the SOME/IP server sample
fd '(prj.conf|main.cpp)' zephyr/samples/someip_serverRepository: vtz/opensomeip
Length of output: 137
🏁 Script executed:
# Check if there are other SOMEIP samples and what E2E configs they use
fd 'prj.conf' zephyr/samples --exec grep -H 'SOMEIP_E2E' {} 2>/dev/nullRepository: vtz/opensomeip
Length of output: 290
🏁 Script executed:
# Look for what CONFIG_SOMEIP_E2E does in Kconfig files
fd 'Kconfig' -exec grep -l 'SOMEIP_E2E' {} 2>/dev/nullRepository: vtz/opensomeip
Length of output: 40
🏁 Script executed:
cat -n zephyr/samples/someip_server/src/main.cppRepository: vtz/opensomeip
Length of output: 4417
🏁 Script executed:
# Check if E2E is referenced in the sample source files
rg -r 'e2e|E2E|e_2_e' zephyr/samples/someip_server --type=cppRepository: vtz/opensomeip
Length of output: 40
🏁 Script executed:
# Let's also check the someip_echo sample since it disables E2E
cat -n zephyr/samples/someip_echo/src/main.cppRepository: vtz/opensomeip
Length of output: 2621
🏁 Script executed:
# Search for E2E in Kconfig or CMakeLists to understand what it controls
rg 'SOMEIP_E2E' --type=cmake --type=conf -B2 -A2Repository: vtz/opensomeip
Length of output: 86
🏁 Script executed:
# Find Kconfig files that mention E2E
fd 'Kconfig' -exec grep -l 'E2E' {} \;Repository: vtz/opensomeip
Length of output: 296
🏁 Script executed:
# Look for CMakeLists or build files that reference E2E
rg 'E2E|e2e' --type=cmakeRepository: vtz/opensomeip
Length of output: 2157
🏁 Script executed:
# Check if there's a Kconfig file in the root or module directory
fd 'Kconfig' | head -20Repository: vtz/opensomeip
Length of output: 72
🏁 Script executed:
# Search for any documentation about E2E in config or comment blocks
rg 'SOMEIP_E2E' -B5 -A5Repository: vtz/opensomeip
Length of output: 4182
CONFIG_SOMEIP_E2E=y is intentionally enabled by default and consistent with other samples.
While this sample does not explicitly use E2E protection features in its code, CONFIG_SOMEIP_E2E defaults to enabled in Kconfig. Most SOME/IP samples (someip_server, someip_client, someip_sd_client) follow this default. Only someip_echo disables it, explicitly described as a "minimal" demo. If the goal is to match that minimal configuration for this sample, consider setting CONFIG_SOMEIP_E2E=n; otherwise, the current setting is standard.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/someip_server/prj.conf` around lines 16 - 23, The prj.conf
currently sets CONFIG_SOMEIP_E2E=y while this sample doesn’t use E2E features;
if you intend this sample to be a minimal demo like someip_echo, change
CONFIG_SOMEIP_E2E to n in prj.conf (modify the CONFIG_SOMEIP_E2E entry) and add
a short inline comment explaining it’s disabled for minimal behavior, otherwise
leave CONFIG_SOMEIP_E2E=y to follow the standard SOME/IP sample defaults.
| /** | ||
| * SOME/IP server running on Zephyr native_sim. | ||
| * | ||
| * Listens on 127.0.0.1:30490 for SOME/IP REQUEST messages, echoes | ||
| * the payload back inside a RESPONSE with a "Server got: " prefix. | ||
| * Demonstrates real UDP networking between two Zephyr processes. | ||
| */ |
There was a problem hiding this comment.
Doc/code mismatch: comment says 127.0.0.1 but code binds to 0.0.0.0.
Line 10 states the server listens on 127.0.0.1:30490, but the Endpoint at Line 37 is constructed with "0.0.0.0" (all interfaces). Update the comment to match the implementation.
📝 Proposed fix
- * Listens on 127.0.0.1:30490 for SOME/IP REQUEST messages, echoes
+ * Listens on 0.0.0.0:30490 for SOME/IP REQUEST messages, echoes📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * SOME/IP server running on Zephyr native_sim. | |
| * | |
| * Listens on 127.0.0.1:30490 for SOME/IP REQUEST messages, echoes | |
| * the payload back inside a RESPONSE with a "Server got: " prefix. | |
| * Demonstrates real UDP networking between two Zephyr processes. | |
| */ | |
| /** | |
| * SOME/IP server running on Zephyr native_sim. | |
| * | |
| * Listens on 0.0.0.0:30490 for SOME/IP REQUEST messages, echoes | |
| * the payload back inside a RESPONSE with a "Server got: " prefix. | |
| * Demonstrates real UDP networking between two Zephyr processes. | |
| */ |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/someip_server/src/main.cpp` around lines 7 - 13, The
file-level comment incorrectly says the server listens on 127.0.0.1:30490 while
the code constructs an Endpoint with "0.0.0.0" (all interfaces) in main
(Endpoint at the top-level/constructor); update the comment to state the server
listens on 0.0.0.0:30490 (or alternatively change the Endpoint construction to
"127.0.0.1" if you intend loopback-only) so the documentation matches the
implementation, referencing the Endpoint usage in main.cpp.
| while (true) { | ||
| platform::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
| } | ||
|
|
||
| return 0; |
There was a problem hiding this comment.
Unreachable return 0; after while (true) loop.
Line 113 is dead code. Most compilers will warn about this. Remove it or restructure if you want a clean build with -Werror.
📝 Proposed fix
while (true) {
platform::this_thread::sleep_for(std::chrono::milliseconds(100));
}
-
- return 0;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| while (true) { | |
| platform::this_thread::sleep_for(std::chrono::milliseconds(100)); | |
| } | |
| return 0; | |
| while (true) { | |
| platform::this_thread::sleep_for(std::chrono::milliseconds(100)); | |
| } | |
| } |
🧰 Tools
🪛 Cppcheck (2.19.0)
[style] 109-109: The function 'set_session_id' is never used.
(unusedFunction)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/someip_server/src/main.cpp` around lines 109 - 113, The final
`return 0;` in main is unreachable because of the infinite `while (true)` loop;
remove the dead `return 0;` or restructure the `while (true)` in main (e.g.,
make it conditional or break on a shutdown condition) so the function can
terminate cleanly and eliminate the compiler warning; locate the infinite loop
and the trailing `return 0;` in main.cpp to apply the change.
The CI container image (ghcr.io/zephyrproject-rtos/ci:v0.27.4) does not include the Zephyr SDK, which is required by FindZephyr-sdk.cmake. Install the minimal SDK for native_sim and add the arm-zephyr-eabi toolchain for ARM cross-compilation jobs.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
.github/workflows/zephyr.yml (1)
40-49:⚠️ Potential issue | 🟠 MajorDon’t mask Zephyr runtime failures with
|| true.These commands will always succeed even if the binary fails or times out, making CI unreliable.
✅ Suggested change
- name: Build & run test_core env: { ZEPHYR_BASE: /tmp/zp/zephyr } run: | west build -b native_sim zephyr/tests/test_core -d build/ns_tc --pristine auto - timeout 30 build/ns_tc/zephyr/zephyr.exe || true + timeout 30 build/ns_tc/zephyr/zephyr.exe - name: Build & run someip_echo env: { ZEPHYR_BASE: /tmp/zp/zephyr } run: | west build -b native_sim zephyr/samples/someip_echo -d build/ns_echo --pristine auto - timeout 30 build/ns_echo/zephyr/zephyr.exe || true + timeout 30 build/ns_echo/zephyr/zephyr.exe🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 40 - 49, The CI currently masks failures by appending "|| true" to the runtime invocations in the "Build & run test_core" and "Build & run someip_echo" steps; remove the "|| true" from the timeout lines so that a failed or timed-out execution returns a non-zero exit and fails the job, e.g., change "timeout 30 build/ns_tc/zephyr/zephyr.exe || true" and "timeout 30 build/ns_echo/zephyr/zephyr.exe || true" to simply run the timeout commands without "|| true" (or alternatively capture the exit code and explicitly exit non-zero) so failures surface in CI.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/zephyr.yml:
- Around line 30-35: The "Install Zephyr SDK" step downloads tarballs without
integrity checks; update that step (and other download steps like "Init Zephyr")
to verify downloads before extraction by fetching or embedding the expected
SHA256 checksum and validating the downloaded file (e.g., using sha256sum -c or
comparing sha256sum output) and fail the job if the checksum does not match;
ensure the verification occurs prior to tar extraction and apply the same
pattern for all toolchain/SDK download steps in this workflow.
---
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 40-49: The CI currently masks failures by appending "|| true" to
the runtime invocations in the "Build & run test_core" and "Build & run
someip_echo" steps; remove the "|| true" from the timeout lines so that a failed
or timed-out execution returns a non-zero exit and fails the job, e.g., change
"timeout 30 build/ns_tc/zephyr/zephyr.exe || true" and "timeout 30
build/ns_echo/zephyr/zephyr.exe || true" to simply run the timeout commands
without "|| true" (or alternatively capture the exit code and explicitly exit
non-zero) so failures surface in CI.
| - name: Install Zephyr SDK | ||
| run: | | ||
| wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz | ||
| tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ | ||
| /opt/zephyr-sdk-0.17.0/setup.sh -c | ||
| - name: Init Zephyr |
There was a problem hiding this comment.
Verify Zephyr SDK downloads with checksums.
The workflow fetches SDK/toolchain tarballs without integrity verification, which is a supply‑chain risk. Add checksum validation (and apply the same approach to the other download steps in this file).
✅ Suggested hardening
- name: Install Zephyr SDK
run: |
wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz
+ echo "${ZEPHYR_SDK_MINIMAL_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c -
tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/
/opt/zephyr-sdk-0.17.0/setup.sh -c🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/zephyr.yml around lines 30 - 35, The "Install Zephyr SDK"
step downloads tarballs without integrity checks; update that step (and other
download steps like "Init Zephyr") to verify downloads before extraction by
fetching or embedding the expected SHA256 checksum and validating the downloaded
file (e.g., using sha256sum -c or comparing sha256sum output) and fail the job
if the checksum does not match; ensure the verification occurs prior to tar
extraction and apply the same pattern for all toolchain/SDK download steps in
this workflow.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/pre-commit.yml:
- Around line 51-56: The script currently checks MSG (commit message) to skip
merge commits; instead detect real merges by parent count: replace the grep on
MSG with a git check that uses the commit SHA (use the variable that holds the
commit hash in this hook) such as running git rev-list --parents -n1
"<commit-sha>" and counting fields (a merge has >2 fields/parents) and only then
skip; reference the existing MSG variable to remove the message-based branch and
use the commit SHA + git rev-list/awk or wc -w logic to detect merges.
| # Skip merge commits (auto-generated by Git) | ||
| if echo "$MSG" | grep -qE "^Merge "; then | ||
| echo "⏭️ Merge commit — skipped" | ||
| echo "" | ||
| continue | ||
| fi |
There was a problem hiding this comment.
Detect merge commits by parent count, not message prefix.
Line 52 skips validation based on commit text (^Merge ), which allows non-merge commits to bypass checks if authored that way. Use commit topology (number of parents) to identify true merge commits.
Suggested fix
- # Skip merge commits (auto-generated by Git)
- if echo "$MSG" | grep -qE "^Merge "; then
+ # Skip true merge commits (commits with 2+ parents)
+ if [ "$(git rev-list --parents -n 1 "$COMMIT" | wc -w)" -gt 2 ]; then
echo "⏭️ Merge commit — skipped"
echo ""
continue
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Skip merge commits (auto-generated by Git) | |
| if echo "$MSG" | grep -qE "^Merge "; then | |
| echo "⏭️ Merge commit — skipped" | |
| echo "" | |
| continue | |
| fi | |
| # Skip true merge commits (commits with 2+ parents) | |
| if [ "$(git rev-list --parents -n 1 "$COMMIT" | wc -w)" -gt 2 ]; then | |
| echo "⏭️ Merge commit — skipped" | |
| echo "" | |
| continue | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pre-commit.yml around lines 51 - 56, The script currently
checks MSG (commit message) to skip merge commits; instead detect real merges by
parent count: replace the grep on MSG with a git check that uses the commit SHA
(use the variable that holds the commit hash in this hook) such as running git
rev-list --parents -n1 "<commit-sha>" and counting fields (a merge has >2
fields/parents) and only then skip; reference the existing MSG variable to
remove the message-based branch and use the commit SHA + git rev-list/awk or wc
-w logic to detect merges.
- Install Zephyr SDK v0.17.0 in CI (the container image lacks it) - Move ZEPHYR_EXTRA_MODULES before find_package(Zephyr) so the SOMEIP Kconfig symbols are registered during configuration - Remove CONFIG_NEWLIB_LIBC=y from all prj.conf files; Zephyr 4.3.x treats the libc choice conflict as fatal on native_sim
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (3)
zephyr/samples/someip_sd_client/prj.conf (1)
23-23:⚠️ Potential issue | 🟡 Minor
CONFIG_SOMEIP_E2E=y— confirm E2E is intentionally used in the SD client.The SD client sample does not obviously perform E2E protection on its frames. If this is carried over unintentionally, set
CONFIG_SOMEIP_E2E=nto reduce the build footprint, consistent with the pattern insomeip_echo/prj.conf.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/someip_sd_client/prj.conf` at line 23, The CONFIG_SOMEIP_E2E option is enabled but the SD client sample doesn't appear to perform E2E protection; either confirm E2E is intentionally required for this sample or disable it to reduce build size by changing CONFIG_SOMEIP_E2E to n. Locate the declaration CONFIG_SOMEIP_E2E in the sample prj.conf and either leave it enabled with a short comment explaining why E2E protection is used here, or set CONFIG_SOMEIP_E2E=n to match the pattern used in someip_echo/prj.conf.zephyr/tests/test_transport/CMakeLists.txt (1)
1-9: LGTM —ZEPHYR_EXTRA_MODULESis now correctly set beforefind_package(Zephyr).The previously flagged ordering issue has been resolved.
SOMEIP_ROOTandZEPHYR_EXTRA_MODULESare both configured at lines 3–4, before thefind_package(Zephyr)call at line 6, ensuring proper Zephyr module discovery.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_transport/CMakeLists.txt` around lines 1 - 9, No changes required: the ordering issue is resolved because SOMEIP_ROOT and ZEPHYR_EXTRA_MODULES are set before invoking find_package(Zephyr); leave the declarations of SOMEIP_ROOT and list(APPEND ZEPHYR_EXTRA_MODULES ...) as-is and keep the find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) call following them to ensure proper Zephyr module discovery (verify symbols: SOMEIP_ROOT, ZEPHYR_EXTRA_MODULES, find_package(Zephyr)).zephyr/tests/test_core/CMakeLists.txt (1)
1-9: LGTM —ZEPHYR_EXTRA_MODULESordering fix applied correctly.Same as
test_transport:SOMEIP_ROOTandZEPHYR_EXTRA_MODULESare both set at lines 3–4, beforefind_package(Zephyr)at line 6. The previously reported ordering issue is resolved.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_core/CMakeLists.txt` around lines 1 - 9, The CMake ordering issue is already fixed: ensure that SOMEIP_ROOT and ZEPHYR_EXTRA_MODULES remain set before calling find_package(Zephyr) and no further changes are required; verify that the symbols SOMEIP_ROOT, ZEPHYR_EXTRA_MODULES, and the find_package(Zephyr) call in CMakeLists.txt keep the current order and commit as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@zephyr/prj.conf`:
- Around line 1-5: Add CONFIG_REQUIRES_FULL_LIBCPP=y to the base configuration
so the full C++ standard library is selected (preventing the minimal libcpp from
being used); update the existing prj.conf that currently contains CONFIG_CPP,
CONFIG_STD_CPP17, and CONFIG_POSIX_API to include CONFIG_REQUIRES_FULL_LIBCPP=y
and ensure any test/sample configs that rely on this base do not override or
omit it (reference: CONFIG_REQUIRES_FULL_LIBCPP, CONFIG_CPP, CONFIG_STD_CPP17,
CONFIG_POSIX_API).
In `@zephyr/samples/hello_s32k/prj.conf`:
- Line 5: The CONFIG_MAIN_STACK_SIZE value is too small for C++17 static
constructors and runtime init; update CONFIG_MAIN_STACK_SIZE from 2048 to a
larger value (recommend at least 4096, or match other samples at 8192) in the
prj.conf so the C++ runtime (global static constructors and exception unwinding)
has sufficient stack during boot.
- Around line 1-5: Add CONFIG_REQUIRES_FULL_LIBCPP=y to enable the full libc++
STL so main.cpp’s use of std::string, std::vector and std::make_shared links
correctly; also consider adding CONFIG_CPP_EXCEPTIONS=y to match other samples
and ensure exception support, and evaluate increasing CONFIG_MAIN_STACK_SIZE
(currently 2048) to 8192 if C++ runtime initialization or static constructors
require more stack like the other SOME/IP examples do.
In `@zephyr/samples/someip_client/prj.conf`:
- Line 10: The build fails because the code in include/platform/net.h expects
the POSIX mapping for socket functions (someip_close_socket mapped to close()),
so add CONFIG_NET_SOCKETS_POSIX_NAMES=y to the sample's prj.conf to enable the
POSIX socket symbol export; update zephyr/samples/someip_client/prj.conf to
include CONFIG_NET_SOCKETS_POSIX_NAMES=y so someip_close_socket and close()
resolve at link time.
In `@zephyr/tests/test_core/prj.conf`:
- Around line 1-2: The test uses std::vector in test_core/src/main.cpp but
prj.conf only enables CONFIG_CPP and CONFIG_STD_CPP17; add
CONFIG_REQUIRES_FULL_LIBCPP=y to prj.conf so the full libstdc++/libc++ (STL) is
available at build time. Ensure the new CONFIG_REQUIRES_FULL_LIBCPP=y entry is
placed alongside CONFIG_CPP and CONFIG_STD_CPP17 so the test can link against
the full C++ library.
In `@zephyr/tests/test_transport/prj.conf`:
- Around line 1-3: Add CONFIG_REQUIRES_FULL_LIBCPP=y to the project config so
the STL headers used in test_transport/src/main.cpp (<thread>, <chrono>,
<atomic>) have full libc++ support; update the prj.conf by adding the
CONFIG_REQUIRES_FULL_LIBCPP flag to match other samples (someip_client,
someip_sd_client) to avoid link-time failures.
---
Duplicate comments:
In `@zephyr/samples/someip_sd_client/prj.conf`:
- Line 23: The CONFIG_SOMEIP_E2E option is enabled but the SD client sample
doesn't appear to perform E2E protection; either confirm E2E is intentionally
required for this sample or disable it to reduce build size by changing
CONFIG_SOMEIP_E2E to n. Locate the declaration CONFIG_SOMEIP_E2E in the sample
prj.conf and either leave it enabled with a short comment explaining why E2E
protection is used here, or set CONFIG_SOMEIP_E2E=n to match the pattern used in
someip_echo/prj.conf.
In `@zephyr/tests/test_core/CMakeLists.txt`:
- Around line 1-9: The CMake ordering issue is already fixed: ensure that
SOMEIP_ROOT and ZEPHYR_EXTRA_MODULES remain set before calling
find_package(Zephyr) and no further changes are required; verify that the
symbols SOMEIP_ROOT, ZEPHYR_EXTRA_MODULES, and the find_package(Zephyr) call in
CMakeLists.txt keep the current order and commit as-is.
In `@zephyr/tests/test_transport/CMakeLists.txt`:
- Around line 1-9: No changes required: the ordering issue is resolved because
SOMEIP_ROOT and ZEPHYR_EXTRA_MODULES are set before invoking
find_package(Zephyr); leave the declarations of SOMEIP_ROOT and list(APPEND
ZEPHYR_EXTRA_MODULES ...) as-is and keep the find_package(Zephyr REQUIRED HINTS
$ENV{ZEPHYR_BASE}) call following them to ensure proper Zephyr module discovery
(verify symbols: SOMEIP_ROOT, ZEPHYR_EXTRA_MODULES, find_package(Zephyr)).
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (12)
zephyr/prj.confzephyr/samples/hello_s32k/prj.confzephyr/samples/net_test/prj.confzephyr/samples/someip_client/prj.confzephyr/samples/someip_echo/CMakeLists.txtzephyr/samples/someip_echo/prj.confzephyr/samples/someip_sd_client/prj.confzephyr/samples/someip_server/prj.confzephyr/tests/test_core/CMakeLists.txtzephyr/tests/test_core/prj.confzephyr/tests/test_transport/CMakeLists.txtzephyr/tests/test_transport/prj.conf
| CONFIG_STD_CPP17=y | ||
|
|
||
| CONFIG_HEAP_MEM_POOL_SIZE=32768 | ||
| CONFIG_MAIN_STACK_SIZE=2048 |
There was a problem hiding this comment.
CONFIG_MAIN_STACK_SIZE=2048 may be too small for C++17 with static constructors.
All other SOME/IP samples in this PR use CONFIG_MAIN_STACK_SIZE=8192. The C++17 runtime initialization path (global static constructors, exception stack unwinding) can exhaust 2 KiB, causing a hard fault at boot. Even for a "hello world" that uses the full C++ library, consider at least 4096.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/hello_s32k/prj.conf` at line 5, The CONFIG_MAIN_STACK_SIZE
value is too small for C++17 static constructors and runtime init; update
CONFIG_MAIN_STACK_SIZE from 2048 to a larger value (recommend at least 4096, or
match other samples at 8192) in the prj.conf so the C++ runtime (global static
constructors and exception unwinding) has sufficient stack during boot.
- Add CONFIG_REQUIRES_FULL_LIBCPP=y to all prj.conf so Zephyr uses the toolchain's full libstdc++ instead of its minimal C++ stub - Replace 4 remaining dynamic_cast with static_cast in SD code to support Zephyr's -fno-rtti - Move endpoint.cpp to the always-built core section so test_core (which disables transport) can link against Endpoint - Add someip_sd_client build to native_sim CI job
Zephyr 4.3.x native_sim no longer defines CONFIG_NATIVE_APPLICATION. Replace all occurrences with CONFIG_ARCH_POSIX across platform headers, source files, and zephyr/CMakeLists.txt. Also fix test_core serializer test to use the actual API names (serialize_uint8, get_buffer, deserialize_uint8, etc.).
- Add #include <cstddef> for size_t in 6 headers that fail under Zephyr's stricter include resolution - Fix BOARD_ROOT to point to zephyr/ (which contains boards/) instead of zephyr/boards/ directly, in CI workflow and all build scripts
- Remove CONFIG_NET_SOCKETS_POSIX_NAMES from all prj.conf (removed in Zephyr 4.3.x; CONFIG_POSIX_API already provides POSIX socket names) - Remove s32k388_renode CI job (missing custom SoC definition)
a984c24 to
627f1b8
Compare
CONFIG_NET_SOCKETS_POSIX_NAMES was removed in Zephyr 4.3.x, leaving <zephyr/net/socket.h> with only zsock_* prefixed functions. Add macro mappings in platform/net.h (socket, bind, close, setsockopt, etc.) to restore POSIX-compatible names. Also provide inet_addr via zsock_inet_pton, in_addr_t typedef, and INADDR_NONE/F_GETFL/O_NONBLOCK constants. - Guard throw in udp_transport.cpp for -fno-exceptions builds - Remove try/catch in tcp_transport.cpp (catch blocks were empty) - Fix test_transport to use platform::this_thread::sleep_for - Add test_transport build step to CI workflow - Update ZEPHYR_PORT_PROGRESS.md with 4.3.x compatibility notes
627f1b8 to
7a594c2
Compare
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/sd/sd_client.cpp (2)
373-394:⚠️ Potential issue | 🟠 MajorCallbacks invoked while holding mutexes — deadlock risk diverges across platforms.
available_callbackis invoked at line 377 whilesubscriptions_mutex_is held, andfind callbackat line 387 while bothsubscriptions_mutex_andpending_finds_mutex_are held. If a callback re-enters the client (e.g., callsunsubscribe_service), it will attempt to re-locksubscriptions_mutex_.On Zephyr,
k_mutexis recursive, so this succeeds. On POSIX,platform::Mutexaliasesstd::mutex, which is not recursive — this would deadlock. This platform-behavioral divergence is a latent bug that should be resolved for correctness on POSIX targets.Consider copying the callback/data out of the locked region and invoking callbacks after releasing the mutex.
Sketch of the fix for handle_service_offer
// Notify subscribers + ServiceAvailableCallback cb_copy; { - platform::ScopedLock lock(subscriptions_mutex_); - auto sub_it = service_subscriptions_.find(instance.service_id); - if (sub_it != service_subscriptions_.end() && sub_it->second.available_callback) { - sub_it->second.available_callback(instance); - } + platform::ScopedLock lock(subscriptions_mutex_); + auto sub_it = service_subscriptions_.find(instance.service_id); + if (sub_it != service_subscriptions_.end() && sub_it->second.available_callback) { + cb_copy = sub_it->second.available_callback; + } + } + if (cb_copy) { + cb_copy(instance); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/sd/sd_client.cpp` around lines 373 - 394, The code invokes callbacks while holding subscriptions_mutex_ (calling available_callback on service_subscriptions_) and pending_finds_mutex_ (calling callback on pending_finds_), risking deadlocks on non-recursive mutex platforms; modify handle_service_offer (or the function containing this block) to copy any callbacks and required data (e.g., sub_it->second.available_callback and each it->second.callback along with the ServiceInstance) out of the locked regions, release the mutexes, and then invoke the copied callbacks outside the locks; ensure you still erase pending_finds_ entries while holding pending_finds_mutex_ but collect callbacks to call after unlocking, and use the same symbols (service_subscriptions_, subscriptions_mutex_, pending_finds_, pending_finds_mutex_, available_callback, callback) to locate and update the code.
343-344:⚠️ Potential issue | 🔴 CriticalFix logic bug that silently drops endpoint information when option index is 0.
At lines 343-344,
run1 = entry.get_index1() ? 1 : 0treats index 0 as invalid, but the server explicitly setsset_index1(0)to reference the first option (verified at sd_server.cpp lines 207, 366, and 536). When index1 is 0, run1 becomes 0, causing the loop at line 346 to never execute:for (uint8_t i = 0; i < run1 && ...withi < 0always false. This means the client never reads endpoint information from the server's own offers, silently dropping critical SOME/IP-SD endpoint data.The correct approach, as shown in sd_server.cpp line 479, is to validate the index against bounds:
if (index1 < options.size())rather than treating the index value as a boolean.Proposed fix
- uint8_t run1 = entry.get_index1() ? 1 : 0; // Simple case: check if index1 is set + // In SOME/IP-SD, index1 references an option by position; option at index 0 is valid. + // A proper "has options" check should use the run length or a dedicated flag. + uint8_t run1 = 1; // Always attempt to read at least one option if options exist🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/sd/sd_client.cpp` around lines 343 - 344, The code treats entry.get_index1() as a boolean which makes index value 0 (valid first option) be considered invalid; change the logic that computes run1 (currently using entry.get_index1() ? 1 : 0) to instead validate the index against the options container (e.g., get index1 into a uint8_t index1 = entry.get_index1(); then set run1 = (index1 < options.size()) ? 1 : 0) so the subsequent loop that reads endpoint information will run when index1 references a valid option; update the reference in the loop that uses run1 accordingly (symbols: entry.get_index1(), index1, run1, options).src/transport/udp_transport.cpp (1)
401-426:⚠️ Potential issue | 🟠 MajorPre-existing bug:
data.resize(received)permanently shrinks the receive buffer.Line 423 shrinks the buffer to the size of the received message. Since
receive_loop(line 334) reuses the samebuffervector across iterations, subsequent calls torecvfromwill use a truncated buffer, potentially dropping data from larger messages.This is not introduced by this PR, but it's worth fixing since the transport is being actively modified.
Proposed fix in receive_loop
void UdpTransport::receive_loop() { std::vector<uint8_t> buffer(config_.receive_buffer_size); while (running_) { Endpoint sender; + buffer.resize(config_.receive_buffer_size); // Reset buffer size each iteration Result result = receive_data(buffer, sender);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/udp_transport.cpp` around lines 401 - 426, The receive method UdpTransport::receive_data currently calls data.resize(received) which permanently shrinks the caller's buffer (used by receive_loop), so change receive_data to avoid mutating the caller's buffer size: capture the original buffer size (e.g., original_size = data.size()), after recvfrom copy the received bytes into a temporary vector (or otherwise compute/return the received length), deliver the actual payload to the caller without permanently resizing the original buffer, and if you must resize temporarily restore data.size() (or reserve original_size) before returning; update receive_loop to use the returned length (or the separate payload) instead of relying on data being truncated. Ensure changes reference UdpTransport::receive_data, receive_loop, and remove the persistent data.resize(received) call.
♻️ Duplicate comments (20)
zephyr/boards/s32k388_renode/s32k388_renode.conf (1)
7-10: 🧹 Nitpick | 🔵 Trivial
CONFIG_NET_MAX_CONTEXTSmay be exhausted by SD sockets — consider raising it.
CONFIG_NET_MAX_CONTEXTSdefaults to 6. Each network context describes a network 5-tuple used when listening or sending network traffic, and each BSD socket uses one network context. SOME/IP Service Discovery opens at least two sockets simultaneously (one multicast, one unicast). Additional service instances will consume further contexts, and the default of 6 can be exhausted quickly, causingsocket()to returnENOMEMsilently at runtime.⚙️ Proposed fix to raise the context limit
CONFIG_NET_SOCKETS=y +CONFIG_NET_MAX_CONTEXTS=16🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/boards/s32k388_renode/s32k388_renode.conf` around lines 7 - 10, The current configuration may exhaust the default network context limit; add or increase CONFIG_NET_MAX_CONTEXTS in the board config (referencing CONFIG_NET_MAX_CONTEXTS) to a higher value (e.g., 12 or 16) so each BSD socket and SOME/IP Service Discovery sockets have enough contexts; update s32k388_renode.conf to set CONFIG_NET_MAX_CONTEXTS=<new_value> and rebuild to verify socket() no longer returns ENOMEM at runtime.docs/ZEPHYR_PORT_PROGRESS.md (2)
6-6: "Targets" anglicism — previously flagged.The rest of the document is in Portuguese; consider replacing with "Alvos" or "Plataformas-alvo" for consistency.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/ZEPHYR_PORT_PROGRESS.md` at line 6, Replace the anglicism "Targets" in the line "**Targets**: native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388)" with a Portuguese term for consistency (e.g., "**Alvos**" or "**Plataformas-alvo**"), keeping the rest of the list unchanged.
304-304: "target" anglicism — previously flagged.Same as above; consider "alvo" for consistency with the document language.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/ZEPHYR_PORT_PROGRESS.md` at line 304, Replace the anglicism "target" with the Portuguese equivalent "alvo" in the documentation line mentioning `scripts/run_zephyr_tests.sh` (the diff line "- Criado `scripts/run_zephyr_tests.sh` -- orquestra build + execucao para cada target") so the phrase reads "...para cada alvo" for consistency with the document language.zephyr/samples/hello_s32k/prj.conf (1)
6-6:CONFIG_MAIN_STACK_SIZE=2048— still potentially undersized for C++ runtime.Other SOME/IP samples in this PR use 8192, and the base
zephyr/prj.confuses 4096. If this sample'smain.cppusesstd::string,std::vector, andstd::make_shared, 2 KiB may be tight depending on the target's C++ runtime initialization overhead (static constructors, stack unwinding info). Consider at least 4096 for safety.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/hello_s32k/prj.conf` at line 6, Increase the main thread stack size variable CONFIG_MAIN_STACK_SIZE from 2048 to at least 4096 (or 8192 to match other SOME/IP samples) to avoid C++ runtime stack exhaustion; update the value in prj.conf and verify main.cpp (usage of std::string, std::vector, std::make_shared and any static C++ initializers) still runs without stack faults after the change.zephyr/tests/test_core/src/main.cpp (1)
97-117: Serializer API usage now matches the current interface — LGTM.The test correctly uses
serialize_uint8/16/32,get_buffer(), and checksis_success()/get_value()on theDeserializationResult, consistent with theserializer.hAPI surface.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_core/src/main.cpp` around lines 97 - 117, No changes required: the test correctly uses Serializer::serialize_uint8/serialize_uint16/serialize_uint32, Serializer::get_buffer(), Deserializer and checks DeserializationResult::is_success() / get_value(); leave test_serializer as-is and approve the change.src/platform/zephyr_memory.cpp (1)
26-33:⚠️ Potential issue | 🟠 Major
ensure_slab_init()is still not thread-safe.Concurrent calls to
allocate_message()can race onslab_initialized, potentially double-initializing the slab. Guard with a mutex or useK_MUTEX_DEFINEwith double-checked locking as previously suggested.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/platform/zephyr_memory.cpp` around lines 26 - 33, ensure_slab_init() currently races on slab_initialized when called concurrently (e.g., from allocate_message()); add a Zephyr mutex (use K_MUTEX_DEFINE(message_slab_mutex)) and apply double-checked locking inside ensure_slab_init(): first check slab_initialized, if false take the mutex, check slab_initialized again, call k_mem_slab_init(&message_slab, message_pool_buffer, sizeof(someip::Message), CONFIG_SOMEIP_MESSAGE_POOL_SIZE) and set slab_initialized = true, then release the mutex; ensure any path that calls ensure_slab_init() (such as allocate_message) continues to call the guarded function rather than accessing slab_initialized directly..github/workflows/zephyr.yml (3)
30-34:⚠️ Potential issue | 🟠 MajorSDK downloads still lack checksum verification.
The
wgetdownloads of the Zephyr SDK tarballs (lines 32, 69–70) have no integrity checks, which is a supply-chain risk. This was raised in a previous review.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 30 - 34, The workflow currently wget's Zephyr SDK tarball and extracts it without verifying integrity; update the Install Zephyr SDK step to download the release checksum (or signature) alongside the tarball, verify the tarball with sha256sum (or gpg --verify if a signature is available) before running tar and setup.sh, and fail the job on mismatch; specifically modify the commands that download and extract zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz (the wget line and subsequent tar/setup.sh invocations) to first fetch the checksum (or .asc), verify it, and only proceed to tar xf and /opt/zephyr-sdk-0.17.0/setup.sh -c when verification succeeds.
40-54:⚠️ Potential issue | 🟠 MajorRuntime test failures still silently swallowed by
|| true.Lines 44, 49, and 54 use
timeout ... || true, masking test binary failures. This was raised in a previous review and remains unaddressed.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 40 - 54, The workflow is silently ignoring test failures because the run commands for the steps named "Build & run test_core", "Build & run test_transport", and "Build & run someip_echo" append "|| true" to the "timeout 30 build/.../zephyr.exe" invocations; remove the "|| true" (or add "set -e" at the top of each run block) so that non‑zero exits from timeout/zephyr.exe propagate and the job fails on test errors.
1-8:⚠️ Potential issue | 🟡 MinorYAML lint issues (bracket/brace spacing, truthy) remain from prior review.
The spacing in flow collections and unquoted
on:key still trigger YAMLlint/actionlint warnings as previously flagged.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 1 - 8, Fix the YAMLLint/actionlint warnings by normalizing flow collection spacing and quoting the ambiguous key: replace the inline flow lists under the "push" and "pull_request" keys (branches and paths-ignore) with properly formatted block sequences (use "-" items) or ensure no spaces inside brackets if you must keep flow style, and quote the top-level on: key (e.g., 'on':) to avoid truthy-key warnings; update the "branches", "paths-ignore", and "pull_request" entries accordingly to eliminate bracket/brace spacing and unquoted-key linter errors.scripts/run_zephyr_tests.sh (1)
51-58:⚠️ Potential issue | 🟠 MajorRuntime test failures are still swallowed by
|| true.
timeout 30 "$build_dir/zephyr/zephyr.exe" 2>&1 || truealways succeeds, andPASSEDis unconditionally incremented. This makes CI green even when tests fail.🐛 Proposed fix
if [ "$board" = "native_sim" ]; then printf " Running...\n" - timeout 30 "$build_dir/zephyr/zephyr.exe" 2>&1 || true - PASSED=$((PASSED + 1)) + if timeout 30 "$build_dir/zephyr/zephyr.exe" 2>&1; then + PASSED=$((PASSED + 1)) + else + echo " Run: FAILED" + FAILED=$((FAILED + 1)) + fi else🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/run_zephyr_tests.sh` around lines 51 - 58, The runtime test currently swallows failures because the line with timeout uses "|| true" and PASSED is incremented unconditionally; change the native_sim branch so you run timeout "$build_dir/zephyr/zephyr.exe" (preserving the 30s limit and 2>&1 redirection) without "|| true", capture the command's exit status (e.g., via if timeout ...; then ...; else ...; fi) and only increment PASSED ($PASSED=$((PASSED + 1))) when the command succeeds; do not increment PASSED on non-zero exit, and ensure failures are reported (echo or exit with non-zero) instead of being ignored — adjust the block that checks if [ "$board" = "native_sim" ] accordingly.include/platform/thread.h (5)
92-94:⚠️ Potential issue | 🔴 CriticalUse
K_THREAD_STACK_SIZEOF(stack_)fork_thread_create.Line 92 passes
sizeof(stack_); Zephyr stack objects can have reserved bytes, so this size is not the correct runtime stack size.🐛 Proposed fix
- k_thread_create(&thread_, stack_, sizeof(stack_), + k_thread_create(&thread_, stack_, K_THREAD_STACK_SIZEOF(stack_), trampoline, this, nullptr, nullptr, K_PRIO_PREEMPT(7), 0, K_NO_WAIT);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 92 - 94, The call to k_thread_create uses sizeof(stack_) which can include reserved bytes; replace that with K_THREAD_STACK_SIZEOF(stack_) to pass the correct runtime stack size. Update the invocation of k_thread_create (the call where trampoline, this, nullptr, nullptr, K_PRIO_PREEMPT(7), 0, K_NO_WAIT are passed) so the third argument uses K_THREAD_STACK_SIZEOF(stack_) instead of sizeof(stack_).
185-190:⚠️ Potential issue | 🟠 Major
sleep_forneeds overflow-safe conversion and explicit chrono include.Line 189 truncates potentially large millisecond values into
int32_t; also this header usesstd::chronodirectly and should include<chrono>explicitly.🐛 Proposed fix
+#include <chrono> +#include <limits> ... template <typename Rep, typename Period> void sleep_for(const std::chrono::duration<Rep, Period>& d) { - auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(d).count(); - k_msleep(static_cast<int32_t>(ms)); + using namespace std::chrono; + auto ms = duration_cast<milliseconds>(d).count(); + if (ms <= 0) return; + while (ms > 0) { + const auto chunk = std::min<long long>(ms, std::numeric_limits<int32_t>::max()); + k_msleep(static_cast<int32_t>(chunk)); + ms -= chunk; + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 185 - 190, The sleep_for template in thread.h uses std::chrono without including <chrono> and casts milliseconds to int32_t unsafely; add an explicit `#include` <chrono> (and <cstdint> or <limits> if not already present), compute the millisecond count as a signed 64-bit integer (e.g., using auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(d).count()), clamp ms into the int32_t range (handle negative durations by clamping to 0 and large values to INT32_MAX) and then call k_msleep(static_cast<int32_t>(clamped_ms)) to avoid overflow/truncation in sleep_for.
172-175:⚠️ Potential issue | 🟠 MajorHost
ConditionVariabletype is API-incompatible with Zephyr wrapper.Line 174 aliases
std::condition_variable, but Zephyr exposeswait(Mutex&). This breaks the cross-platform abstraction contract.♻️ Proposed host wrapper shape
-using ConditionVariable = std::condition_variable; +class ConditionVariable { +public: + void notify_one() { cv_.notify_one(); } + void notify_all() { cv_.notify_all(); } + void wait(Mutex& mtx) { + std::unique_lock<std::mutex> lk(mtx, std::adopt_lock); + cv_.wait(lk); + lk.release(); + } + template <typename Pred> + void wait(Mutex& mtx, Pred pred) { + std::unique_lock<std::mutex> lk(mtx, std::adopt_lock); + cv_.wait(lk, pred); + lk.release(); + } +private: + std::condition_variable cv_; +};🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 172 - 175, The host alias for ConditionVariable is API-incompatible with the Zephyr wrapper because std::condition_variable requires a std::unique_lock, while Zephyr exposes wait(Mutex&); update the host side in include/platform/thread.h by replacing the using ConditionVariable = std::condition_variable; with a type that supports wait(Mutex&) (e.g., std::condition_variable_any) and ensure ScopedLock is defined against the Mutex alias (ScopedLock = std::scoped_lock<Mutex>) so the cross-platform ConditionVariable::wait(Mutex&) usage works with the existing Mutex/ScopedLock/Thread abstractions.
97-97:⚠️ Potential issue | 🔴 CriticalDestructor is unsafe while thread is still joinable.
Line 97 default-destroys the object even if the Zephyr thread is still running, which can free
stack_while it is still in use.🐛 Proposed fix
- ~Thread() = default; + ~Thread() { + if (joinable()) { + k_thread_abort(&thread_); + joined_ = true; + } + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` at line 97, The default ~Thread() is unsafe because it can free stack_ while the Zephyr thread is still running; replace the default destructor with an implementation that checks if the thread is joinable (e.g., using joinable() or is_joinable()) and, if so, calls join() (or otherwise ensures the thread is stopped) before freeing stack_; alternatively delete the destructor and require callers to call join() explicitly, but ensure stack_ is only released after join() completes in the Thread class (reference: class Thread, ~Thread(), member stack_, and join()/joinable()).
108-127:⚠️ Potential issue | 🔴 CriticalMove operations are invalid for live
k_threadstate.Lines 108-127
memcpykernel thread internals and stack memory, while the trampoline still references the original object address (thispassed at Line 93). This is a correctness blocker.🐛 Proposed fix (minimum safe step)
- Thread(Thread&& o) noexcept - : entry_(std::move(o.entry_)), joined_(o.joined_) { - std::memcpy(&thread_, &o.thread_, sizeof(thread_)); - std::memcpy(stack_, o.stack_, sizeof(stack_)); - o.entry_ = nullptr; - o.joined_ = true; - } - - Thread& operator=(Thread&& o) noexcept { - if (this != &o) { - if (joinable()) join(); - entry_ = std::move(o.entry_); - joined_ = o.joined_; - std::memcpy(&thread_, &o.thread_, sizeof(thread_)); - std::memcpy(stack_, o.stack_, sizeof(stack_)); - o.entry_ = nullptr; - o.joined_ = true; - } - return *this; - } + Thread(Thread&&) = delete; + Thread& operator=(Thread&&) = delete;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 108 - 127, The move ctor Thread(Thread&&) and move assignment operator operator=(Thread&&) incorrectly memcpy kernel thread internals (thread_, stack_) while a live k_thread/trampoline still references the original object; remove the memcpy-based transfer and make Thread non-movable for live threads: either delete the move constructor and move assignment entirely or guard moves to only occur when the source is not joinable (use joinable()/join() or assert !o.joinable()), and ensure entry_, joined_ are transferred safely without copying kernel internals (do not copy thread_ or stack_ for live threads). Use the symbols Thread(Thread&&), operator=(Thread&&), joinable(), join(), entry_, thread_, and stack_ to locate and implement the change.include/platform/net.h (1)
122-133:⚠️ Potential issue | 🔴 CriticalAdd
_WIN32implementations for non-blocking helpers.Lines 122-133 exclude Windows, but transport code calls
someip_set_blocking/someip_set_nonblockingunconditionally. This is a Windows build blocker.🐛 Proposed fix
-/* Portable non-blocking mode */ -#if !defined(_WIN32) +/* Portable non-blocking mode */ +#if defined(_WIN32) +static inline int someip_set_nonblocking(SOCKET fd) { + u_long mode = 1; + return ioctlsocket(fd, FIONBIO, &mode) == 0 ? 0 : -1; +} +static inline int someip_set_blocking(SOCKET fd) { + u_long mode = 0; + return ioctlsocket(fd, FIONBIO, &mode) == 0 ? 0 : -1; +} +#else static inline int someip_set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags < 0) return -1; return fcntl(fd, F_SETFL, flags | O_NONBLOCK); } static inline int someip_set_blocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags < 0) return -1; return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); } `#endif`#!/bin/bash # Verify helper definitions and call sites that require them. rg -n "someip_set_nonblocking|someip_set_blocking" include/platform/net.h src/transport/tcp_transport.cpp🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/net.h` around lines 122 - 133, The build fails on Windows because someip_set_nonblocking and someip_set_blocking are only defined for non-Windows platforms; add equivalent _WIN32 implementations in include/platform/net.h so callers can use them unconditionally. Implement Windows versions that use ioctlsocket/FIONBIO (or SetNamedPipeHandleState/SetFileIoOverlappedRange as appropriate) to toggle non-blocking mode and return 0 on success / -1 on failure, and ensure the function signatures remain static inline int someip_set_nonblocking(int fd) and static inline int someip_set_blocking(int fd) so existing call sites (e.g., in src/transport/tcp_transport.cpp) compile without changes.src/transport/tcp_transport.cpp (1)
207-212:⚠️ Potential issue | 🟠 MajorCheck and handle failures when toggling listen socket mode.
Lines 207-212 ignore
someip_set_blocking/someip_set_nonblockingreturn values. If restoring non-blocking fails, the accept loop can remain blocking.🐛 Proposed fix
- someip_set_blocking(listen_socket_fd_); + if (someip_set_blocking(listen_socket_fd_) < 0) { + return -1; + } int client_fd = accept(listen_socket_fd_, (sockaddr*)&client_addr, &client_len); - someip_set_nonblocking(listen_socket_fd_); + if (someip_set_nonblocking(listen_socket_fd_) < 0) { + if (client_fd >= 0) { + someip_close_socket(client_fd); + } + return -1; + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/tcp_transport.cpp` around lines 207 - 212, The calls to someip_set_blocking(listen_socket_fd_) and someip_set_nonblocking(listen_socket_fd_) are unchecked so a failure could leave the server socket in blocking mode; update the accept sequence to check both return values, handle errors (log via the module logger, return/abort the accept loop or close sockets as appropriate) and ensure you do not proceed if restoring non-blocking fails. Specifically, around the accept() call check the return of someip_set_blocking and someip_set_nonblocking, on failure log a descriptive error referencing listen_socket_fd_, if blocking setup failed avoid calling accept, and if restoring non-blocking fails after accept then close client_fd (or close listen_socket_fd_ and break the loop) to avoid leaving the server stuck in blocking mode.zephyr/tests/test_transport/src/main.cpp (2)
51-75:⚠️ Potential issue | 🟠 MajorTest continues execution after CHECK failures and has no bounded wait for message reception.
If
server.start()fails (line 52), execution continues toget_local_endpoint(),send_message(), etc., likely causing undefined behavior or misleading failures. The singlereceive_message()call at line 74 after a fixed 100ms sleep is also fragile — on a loaded CI host or Zephyr sim, the message may not yet be queued.Add early returns on critical failures and a bounded polling loop for reception.
Proposed fix
UdpTransport server(server_ep, config); auto result = server.start(); CHECK(result == Result::SUCCESS, "server_start"); + if (result != Result::SUCCESS) return; auto bound_ep = server.get_local_endpoint(); printf(" Server bound to port %d\n", bound_ep.get_port()); Message msg(MessageId(0xABCD, 0x0001), RequestId(0x0001, 0x0001), MessageType::REQUEST, ReturnCode::E_OK); msg.set_payload({0x01, 0x02, 0x03}); Endpoint client_ep("127.0.0.1", 0); UdpTransport client(client_ep, config); result = client.start(); CHECK(result == Result::SUCCESS, "client_start"); + if (result != Result::SUCCESS) { server.stop(); return; } result = client.send_message(msg, bound_ep); CHECK(result == Result::SUCCESS, "send_message"); + if (result != Result::SUCCESS) { client.stop(); server.stop(); return; } - platform::this_thread::sleep_for(std::chrono::milliseconds(100)); - - auto received = server.receive_message(); + // Bounded wait for message reception + MessagePtr received = nullptr; + for (int i = 0; i < 50 && !received; ++i) { + platform::this_thread::sleep_for(std::chrono::milliseconds(20)); + received = server.receive_message(); + } CHECK(received != nullptr, "receive_message");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_transport/src/main.cpp` around lines 51 - 75, The test continues after critical CHECK failures and uses a single fixed sleep before one receive attempt; update the test to bail out immediately when critical operations fail (check the return of UdpTransport::start for both server and client and return/FAIL the test rather than continuing) and replace the single sleep+receive call with a bounded polling loop that repeatedly calls server.receive_message() with short sleeps (using platform::this_thread::sleep_for) until a deadline (e.g., total timeout) is reached; reference UdpTransport::start, UdpTransport::get_local_endpoint, UdpTransport::send_message, and UdpTransport::receive_message when adding the early returns and the timed polling loop so the test reliably stops on start failures and waits deterministically for incoming messages.
47-47: Hard-coded127.0.0.1requiresCONFIG_NET_LOOPBACK=yinprj.conf.Already flagged in
prj.confreview — once loopback is enabled there, these addresses will work. Alternatively, replace with the configured IPv4 address (CONFIG_NET_CONFIG_MY_IPV4_ADDR).Also applies to: 64-64
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_transport/src/main.cpp` at line 47, The test currently constructs Endpoint server_ep("127.0.0.1", 0) which requires CONFIG_NET_LOOPBACK=y; update the test to avoid hard-coded loopback or make it conditional: either use the configured IPv4 address macro (CONFIG_NET_CONFIG_MY_IPV4_ADDR) when available or gate the use of "127.0.0.1" behind a build-time check that CONFIG_NET_LOOPBACK is enabled; locate the Endpoint construction in main.cpp (symbol: Endpoint server_ep) and replace the literal "127.0.0.1" with the chosen config macro or add an `#if` CONFIG_NET_LOOPBACK / `#else` branch to select the configured IP so the test runs without forcing loopback to be enabled.zephyr/tests/test_transport/prj.conf (1)
6-9:⚠️ Potential issue | 🟠 MajorMissing
CONFIG_NET_LOOPBACK=y— the test sends to127.0.0.1which requires the loopback interface.The test in
main.cppusesEndpoint("127.0.0.1", 0)for both server and client. On Zephyr'snative_sim, the loopback interface is not enabled by default, so packets to127.0.0.1will not be delivered.Proposed fix
CONFIG_NETWORKING=y CONFIG_NET_IPV4=y CONFIG_NET_UDP=y CONFIG_NET_SOCKETS=y +CONFIG_NET_LOOPBACK=y🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_transport/prj.conf` around lines 6 - 9, The test uses Endpoint("127.0.0.1", 0) but the loopback interface is not enabled; add CONFIG_NET_LOOPBACK=y to the Zephyr configuration so the native_sim loopback delivers 127.0.0.1 packets. Update the prj.conf entry that defines network configs (where CONFIG_NETWORKING, CONFIG_NET_IPV4, CONFIG_NET_UDP, CONFIG_NET_SOCKETS are set) to include CONFIG_NET_LOOPBACK=y so the server/client communication on 127.0.0.1 works.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/zephyr.yml:
- Around line 79-81: The BOARD_ROOT value in the workflow is incorrect and
unquoted: change the -DBOARD_ROOT assignment so it matches the helper scripts
(use the zephyr directory itself, e.g., -DBOARD_ROOT="$ZEPHYR_DIR" /
"$GITHUB_WORKSPACE/zephyr") rather than .../zephyr/boards, and ensure the
$GITHUB_WORKSPACE expansion is quoted to avoid word-splitting; update the
workflow entry that currently sets -DBOARD_ROOT=$GITHUB_WORKSPACE/zephyr/boards
to use -DBOARD_ROOT="$GITHUB_WORKSPACE/zephyr" (consistent with
scripts/run_zephyr_tests.sh and scripts/zephyr_build.sh).
In `@docs/ZEPHYR_PORT_PROGRESS.md`:
- Around line 26-28: Update the note to stop saying CONFIG_REQUIRES_FULL_LIBCPP
"foi substituido" por CONFIG_NEWLIB_LIBC and instead explain their relationship:
state that CONFIG_NEWLIB_LIBC remains the option to select Newlib as the C
library, while CONFIG_REQUIRES_FULL_LIBCPP requests selection of a full C++
standard library and is complementary (not a replacement), and keep the warning
about NEWLIB_LIBC conflicting with EXTERNAL_LIBC in native_sim (Kconfig warnings
fatal in 4.3.x) so readers understand both options may be used together.
In `@include/platform/memory.h`:
- Around line 31-42: The non-Zephyr branch defines allocate_message() but omits
release_message(), breaking API symmetry; add an inline release_message(Message*
msg) stub in the `#else` block (matching the Zephyr signature) that is a no-op (or
forwards to delete if using raw pointers) so platform::release_message() is
always available; ensure the function uses the same types (MessagePtr/Message)
and is declared/defined alongside allocate_message() for consistency.
In `@scripts/run_renode_test.sh`:
- Line 56: The current invocation using renode ... start; sleep 10; quit
swallows the firmware exit status because Renode's quit always returns 0 and the
hardcoded sleep 10 is fragile; update the script that builds the renode command
(references: RENODE_SCRIPT, ELF_PATH, the use of start; sleep 10; quit, and
test_core firmware) to either (a) use Renode's built‑in test
infrastructure/`test` commands in the RENODE_SCRIPT so Renode will emit/pass
through a test status, or (b) remove the fixed sleep and instead read and tail
Renode's UART/log output for explicit PASS/FAIL markers and block until one
appears (with a timeout), then propagate a non‑zero exit code on FAIL; ensure
the wrapper script exits with the propagated status from the parsed marker or
test result rather than relying on Renode's quit.
In `@src/platform/zephyr_memory.cpp`:
- Around line 21-22: The static buffer message_pool_buffer is aligned to a
hardcoded 8 bytes which may be insufficient for someip::Message; change the
alignment to use the type's alignment (alignof(someip::Message)) instead of
__aligned(8) so placement-new is safe—update the declaration of
message_pool_buffer to apply alignment based on alignof(someip::Message)
(referencing message_pool_buffer and someip::Message) using your platform's
alignment attribute/macro.
- Around line 52-56: In release_message, k_mem_slab_free is being called with
msg (a void*), but Zephyr v0.27.4 expects a void**; update the call in the
function release_message so it passes the address of the pointer (use &msg) to
k_mem_slab_free(&message_slab, &msg) after destroying the object with
msg->~Message(); keep the existing msg null-check and destructor call but change
only the second argument to k_mem_slab_free to &msg to match the v0.27.4 API.
In `@src/sd/sd_server.cpp`:
- Around line 365-367: The code repeatedly retrieves an entry added via
add_entry(...) and does a static_cast on sd_message.get_entries()[i].get() (seen
in send_service_offer, send_service_offer_to_client and sd_client.cpp), which is
correct but duplicated and brittle; introduce a small helper to centralize the
cast—either a template method like get_entry_as<T>(SdMessage&, size_t idx) or an
add_entry variant that returns the concrete pointer after insertion (e.g.,
add_entry_and_get<T>(std::unique_ptr<T>)), then replace direct static_cast uses
in send_service_offer/send_service_offer_to_client (and sd_client.cpp) with the
helper to ensure the cast is performed in one place and reduce risk of
index/order mistakes.
- Line 23: The source uses inet_addr (a macro) without directly including its
header; add an explicit `#include` "platform/net.h" at the top of sd_server.cpp so
the dependency is clear and not reliant on transitive includes (this makes
inet_addr's definition explicit and improves maintainability).
In `@src/transport/udp_transport.cpp`:
- Around line 33-37: The constructor currently skips signalling an invalid
local_endpoint_ when exceptions are disabled, leaving UdpTransport in a broken
state; update initialization and lifecycle checks so callers can detect failure:
either set an internal bool (e.g., valid_ or initialized_) when local_endpoint_
is valid in the UdpTransport constructor and expose is_valid(), or perform the
same validation in start() (before bind_socket) and return/propagate an error if
invalid; ensure all code paths that rely on local_endpoint_ (bind_socket, start)
check this flag or validation and fail fast with a clear error/return code
rather than silently proceeding.
In `@zephyr/samples/net_test/prj.conf`:
- Around line 20-29: The PR sets aggressive global Kconfig values
(CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT, CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT,
CONFIG_NET_MAX_CONTEXTS, CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_BUF_TX_COUNT,
CONFIG_NET_PKT_RX_COUNT, CONFIG_NET_PKT_TX_COUNT, CONFIG_HEAP_MEM_POOL_SIZE,
CONFIG_MAIN_STACK_SIZE) in the sample prj.conf which harms portability; remove
or revert these hard-coded high values from this shared sample and instead place
them in board-specific overlay files (or conditional Kconfig fragments) for
boards that need larger resources, ensuring the sample uses conservative
defaults or leaves them unset so targets with tight RAM are not broken.
- Around line 17-18: The PR currently enables CONFIG_NET_SHELL=y
unconditionally; restrict it to debug builds by moving or gating that setting
into a debug-specific overlay (e.g., an overlay file or a config fragment
applied only for debug/bring-up), leaving CONFIG_NET_LOG_LEVEL_INF=y in the base
prj.conf; update references to CONFIG_NET_SHELL so it is only defined in the
debug overlay and remove it from the main prj.conf to avoid increasing footprint
and runtime exposure in release builds.
---
Outside diff comments:
In `@src/sd/sd_client.cpp`:
- Around line 373-394: The code invokes callbacks while holding
subscriptions_mutex_ (calling available_callback on service_subscriptions_) and
pending_finds_mutex_ (calling callback on pending_finds_), risking deadlocks on
non-recursive mutex platforms; modify handle_service_offer (or the function
containing this block) to copy any callbacks and required data (e.g.,
sub_it->second.available_callback and each it->second.callback along with the
ServiceInstance) out of the locked regions, release the mutexes, and then invoke
the copied callbacks outside the locks; ensure you still erase pending_finds_
entries while holding pending_finds_mutex_ but collect callbacks to call after
unlocking, and use the same symbols (service_subscriptions_,
subscriptions_mutex_, pending_finds_, pending_finds_mutex_, available_callback,
callback) to locate and update the code.
- Around line 343-344: The code treats entry.get_index1() as a boolean which
makes index value 0 (valid first option) be considered invalid; change the logic
that computes run1 (currently using entry.get_index1() ? 1 : 0) to instead
validate the index against the options container (e.g., get index1 into a
uint8_t index1 = entry.get_index1(); then set run1 = (index1 < options.size()) ?
1 : 0) so the subsequent loop that reads endpoint information will run when
index1 references a valid option; update the reference in the loop that uses
run1 accordingly (symbols: entry.get_index1(), index1, run1, options).
In `@src/transport/udp_transport.cpp`:
- Around line 401-426: The receive method UdpTransport::receive_data currently
calls data.resize(received) which permanently shrinks the caller's buffer (used
by receive_loop), so change receive_data to avoid mutating the caller's buffer
size: capture the original buffer size (e.g., original_size = data.size()),
after recvfrom copy the received bytes into a temporary vector (or otherwise
compute/return the received length), deliver the actual payload to the caller
without permanently resizing the original buffer, and if you must resize
temporarily restore data.size() (or reserve original_size) before returning;
update receive_loop to use the returned length (or the separate payload) instead
of relying on data being truncated. Ensure changes reference
UdpTransport::receive_data, receive_loop, and remove the persistent
data.resize(received) call.
---
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 30-34: The workflow currently wget's Zephyr SDK tarball and
extracts it without verifying integrity; update the Install Zephyr SDK step to
download the release checksum (or signature) alongside the tarball, verify the
tarball with sha256sum (or gpg --verify if a signature is available) before
running tar and setup.sh, and fail the job on mismatch; specifically modify the
commands that download and extract zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz
(the wget line and subsequent tar/setup.sh invocations) to first fetch the
checksum (or .asc), verify it, and only proceed to tar xf and
/opt/zephyr-sdk-0.17.0/setup.sh -c when verification succeeds.
- Around line 40-54: The workflow is silently ignoring test failures because the
run commands for the steps named "Build & run test_core", "Build & run
test_transport", and "Build & run someip_echo" append "|| true" to the "timeout
30 build/.../zephyr.exe" invocations; remove the "|| true" (or add "set -e" at
the top of each run block) so that non‑zero exits from timeout/zephyr.exe
propagate and the job fails on test errors.
- Around line 1-8: Fix the YAMLLint/actionlint warnings by normalizing flow
collection spacing and quoting the ambiguous key: replace the inline flow lists
under the "push" and "pull_request" keys (branches and paths-ignore) with
properly formatted block sequences (use "-" items) or ensure no spaces inside
brackets if you must keep flow style, and quote the top-level on: key (e.g.,
'on':) to avoid truthy-key warnings; update the "branches", "paths-ignore", and
"pull_request" entries accordingly to eliminate bracket/brace spacing and
unquoted-key linter errors.
In `@docs/ZEPHYR_PORT_PROGRESS.md`:
- Line 6: Replace the anglicism "Targets" in the line "**Targets**: native_sim,
mr_canhubk3 (S32K344), s32k388_renode (S32K388)" with a Portuguese term for
consistency (e.g., "**Alvos**" or "**Plataformas-alvo**"), keeping the rest of
the list unchanged.
- Line 304: Replace the anglicism "target" with the Portuguese equivalent "alvo"
in the documentation line mentioning `scripts/run_zephyr_tests.sh` (the diff
line "- Criado `scripts/run_zephyr_tests.sh` -- orquestra build + execucao para
cada target") so the phrase reads "...para cada alvo" for consistency with the
document language.
In `@include/platform/net.h`:
- Around line 122-133: The build fails on Windows because someip_set_nonblocking
and someip_set_blocking are only defined for non-Windows platforms; add
equivalent _WIN32 implementations in include/platform/net.h so callers can use
them unconditionally. Implement Windows versions that use ioctlsocket/FIONBIO
(or SetNamedPipeHandleState/SetFileIoOverlappedRange as appropriate) to toggle
non-blocking mode and return 0 on success / -1 on failure, and ensure the
function signatures remain static inline int someip_set_nonblocking(int fd) and
static inline int someip_set_blocking(int fd) so existing call sites (e.g., in
src/transport/tcp_transport.cpp) compile without changes.
In `@include/platform/thread.h`:
- Around line 92-94: The call to k_thread_create uses sizeof(stack_) which can
include reserved bytes; replace that with K_THREAD_STACK_SIZEOF(stack_) to pass
the correct runtime stack size. Update the invocation of k_thread_create (the
call where trampoline, this, nullptr, nullptr, K_PRIO_PREEMPT(7), 0, K_NO_WAIT
are passed) so the third argument uses K_THREAD_STACK_SIZEOF(stack_) instead of
sizeof(stack_).
- Around line 185-190: The sleep_for template in thread.h uses std::chrono
without including <chrono> and casts milliseconds to int32_t unsafely; add an
explicit `#include` <chrono> (and <cstdint> or <limits> if not already present),
compute the millisecond count as a signed 64-bit integer (e.g., using auto ms =
std::chrono::duration_cast<std::chrono::milliseconds>(d).count()), clamp ms into
the int32_t range (handle negative durations by clamping to 0 and large values
to INT32_MAX) and then call k_msleep(static_cast<int32_t>(clamped_ms)) to avoid
overflow/truncation in sleep_for.
- Around line 172-175: The host alias for ConditionVariable is API-incompatible
with the Zephyr wrapper because std::condition_variable requires a
std::unique_lock, while Zephyr exposes wait(Mutex&); update the host side in
include/platform/thread.h by replacing the using ConditionVariable =
std::condition_variable; with a type that supports wait(Mutex&) (e.g.,
std::condition_variable_any) and ensure ScopedLock is defined against the Mutex
alias (ScopedLock = std::scoped_lock<Mutex>) so the cross-platform
ConditionVariable::wait(Mutex&) usage works with the existing
Mutex/ScopedLock/Thread abstractions.
- Line 97: The default ~Thread() is unsafe because it can free stack_ while the
Zephyr thread is still running; replace the default destructor with an
implementation that checks if the thread is joinable (e.g., using joinable() or
is_joinable()) and, if so, calls join() (or otherwise ensures the thread is
stopped) before freeing stack_; alternatively delete the destructor and require
callers to call join() explicitly, but ensure stack_ is only released after
join() completes in the Thread class (reference: class Thread, ~Thread(), member
stack_, and join()/joinable()).
- Around line 108-127: The move ctor Thread(Thread&&) and move assignment
operator operator=(Thread&&) incorrectly memcpy kernel thread internals
(thread_, stack_) while a live k_thread/trampoline still references the original
object; remove the memcpy-based transfer and make Thread non-movable for live
threads: either delete the move constructor and move assignment entirely or
guard moves to only occur when the source is not joinable (use joinable()/join()
or assert !o.joinable()), and ensure entry_, joined_ are transferred safely
without copying kernel internals (do not copy thread_ or stack_ for live
threads). Use the symbols Thread(Thread&&), operator=(Thread&&), joinable(),
join(), entry_, thread_, and stack_ to locate and implement the change.
In `@scripts/run_zephyr_tests.sh`:
- Around line 51-58: The runtime test currently swallows failures because the
line with timeout uses "|| true" and PASSED is incremented unconditionally;
change the native_sim branch so you run timeout "$build_dir/zephyr/zephyr.exe"
(preserving the 30s limit and 2>&1 redirection) without "|| true", capture the
command's exit status (e.g., via if timeout ...; then ...; else ...; fi) and
only increment PASSED ($PASSED=$((PASSED + 1))) when the command succeeds; do
not increment PASSED on non-zero exit, and ensure failures are reported (echo or
exit with non-zero) instead of being ignored — adjust the block that checks if [
"$board" = "native_sim" ] accordingly.
In `@src/platform/zephyr_memory.cpp`:
- Around line 26-33: ensure_slab_init() currently races on slab_initialized when
called concurrently (e.g., from allocate_message()); add a Zephyr mutex (use
K_MUTEX_DEFINE(message_slab_mutex)) and apply double-checked locking inside
ensure_slab_init(): first check slab_initialized, if false take the mutex, check
slab_initialized again, call k_mem_slab_init(&message_slab, message_pool_buffer,
sizeof(someip::Message), CONFIG_SOMEIP_MESSAGE_POOL_SIZE) and set
slab_initialized = true, then release the mutex; ensure any path that calls
ensure_slab_init() (such as allocate_message) continues to call the guarded
function rather than accessing slab_initialized directly.
In `@src/transport/tcp_transport.cpp`:
- Around line 207-212: The calls to someip_set_blocking(listen_socket_fd_) and
someip_set_nonblocking(listen_socket_fd_) are unchecked so a failure could leave
the server socket in blocking mode; update the accept sequence to check both
return values, handle errors (log via the module logger, return/abort the accept
loop or close sockets as appropriate) and ensure you do not proceed if restoring
non-blocking fails. Specifically, around the accept() call check the return of
someip_set_blocking and someip_set_nonblocking, on failure log a descriptive
error referencing listen_socket_fd_, if blocking setup failed avoid calling
accept, and if restoring non-blocking fails after accept then close client_fd
(or close listen_socket_fd_ and break the loop) to avoid leaving the server
stuck in blocking mode.
In `@zephyr/boards/s32k388_renode/s32k388_renode.conf`:
- Around line 7-10: The current configuration may exhaust the default network
context limit; add or increase CONFIG_NET_MAX_CONTEXTS in the board config
(referencing CONFIG_NET_MAX_CONTEXTS) to a higher value (e.g., 12 or 16) so each
BSD socket and SOME/IP Service Discovery sockets have enough contexts; update
s32k388_renode.conf to set CONFIG_NET_MAX_CONTEXTS=<new_value> and rebuild to
verify socket() no longer returns ENOMEM at runtime.
In `@zephyr/samples/hello_s32k/prj.conf`:
- Line 6: Increase the main thread stack size variable CONFIG_MAIN_STACK_SIZE
from 2048 to at least 4096 (or 8192 to match other SOME/IP samples) to avoid C++
runtime stack exhaustion; update the value in prj.conf and verify main.cpp
(usage of std::string, std::vector, std::make_shared and any static C++
initializers) still runs without stack faults after the change.
In `@zephyr/tests/test_core/src/main.cpp`:
- Around line 97-117: No changes required: the test correctly uses
Serializer::serialize_uint8/serialize_uint16/serialize_uint32,
Serializer::get_buffer(), Deserializer and checks
DeserializationResult::is_success() / get_value(); leave test_serializer as-is
and approve the change.
In `@zephyr/tests/test_transport/prj.conf`:
- Around line 6-9: The test uses Endpoint("127.0.0.1", 0) but the loopback
interface is not enabled; add CONFIG_NET_LOOPBACK=y to the Zephyr configuration
so the native_sim loopback delivers 127.0.0.1 packets. Update the prj.conf entry
that defines network configs (where CONFIG_NETWORKING, CONFIG_NET_IPV4,
CONFIG_NET_UDP, CONFIG_NET_SOCKETS are set) to include CONFIG_NET_LOOPBACK=y so
the server/client communication on 127.0.0.1 works.
In `@zephyr/tests/test_transport/src/main.cpp`:
- Around line 51-75: The test continues after critical CHECK failures and uses a
single fixed sleep before one receive attempt; update the test to bail out
immediately when critical operations fail (check the return of
UdpTransport::start for both server and client and return/FAIL the test rather
than continuing) and replace the single sleep+receive call with a bounded
polling loop that repeatedly calls server.receive_message() with short sleeps
(using platform::this_thread::sleep_for) until a deadline (e.g., total timeout)
is reached; reference UdpTransport::start, UdpTransport::get_local_endpoint,
UdpTransport::send_message, and UdpTransport::receive_message when adding the
early returns and the timed polling loop so the test reliably stops on start
failures and waits deterministically for incoming messages.
- Line 47: The test currently constructs Endpoint server_ep("127.0.0.1", 0)
which requires CONFIG_NET_LOOPBACK=y; update the test to avoid hard-coded
loopback or make it conditional: either use the configured IPv4 address macro
(CONFIG_NET_CONFIG_MY_IPV4_ADDR) when available or gate the use of "127.0.0.1"
behind a build-time check that CONFIG_NET_LOOPBACK is enabled; locate the
Endpoint construction in main.cpp (symbol: Endpoint server_ep) and replace the
literal "127.0.0.1" with the chosen config macro or add an `#if`
CONFIG_NET_LOOPBACK / `#else` branch to select the configured IP so the test runs
without forcing loopback to be enabled.
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (31)
.github/workflows/zephyr.ymldocs/ZEPHYR_PORT_PROGRESS.mdinclude/core/session_manager.hinclude/e2e/e2e_crc.hinclude/e2e/e2e_header.hinclude/platform/memory.hinclude/platform/net.hinclude/platform/thread.hinclude/tp/tp_reassembler.hinclude/tp/tp_types.hinclude/transport/tcp_transport.hscripts/run_renode_test.shscripts/run_zephyr_tests.shscripts/zephyr_build.shsrc/platform/zephyr_memory.cppsrc/platform/zephyr_thread.cppsrc/sd/sd_client.cppsrc/sd/sd_message.cppsrc/sd/sd_server.cppsrc/transport/tcp_transport.cppsrc/transport/udp_transport.cppzephyr/CMakeLists.txtzephyr/boards/s32k388_renode/s32k388_renode.confzephyr/prj.confzephyr/samples/hello_s32k/prj.confzephyr/samples/net_test/prj.confzephyr/samples/someip_echo/prj.confzephyr/tests/test_core/prj.confzephyr/tests/test_core/src/main.cppzephyr/tests/test_transport/prj.confzephyr/tests/test_transport/src/main.cpp
docs/ZEPHYR_PORT_PROGRESS.md
Outdated
| > **Nota (Zephyr 4.3.x)**: `CONFIG_NEWLIB_LIBC` foi substituido por | ||
| > `CONFIG_REQUIRES_FULL_LIBCPP=y`. Na `native_sim`, `NEWLIB_LIBC` conflita com | ||
| > `EXTERNAL_LIBC` (Kconfig warnings sao fatais em 4.3.x). |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Zephyr 4.3 CONFIG_NEWLIB_LIBC CONFIG_REQUIRES_FULL_LIBCPP
💡 Result:
CONFIG_NEWLIB_LIBC (Zephyr 4.3)
Selects Newlib as Zephyr’s C standard library (the Newlib binaries are expected to come from your toolchain/SDK, e.g., Zephyr SDK). (docs.zephyrproject.org)
- To force full Newlib (not nano): set
CONFIG_NEWLIB_LIBC=yand do not enableCONFIG_NEWLIB_LIBC_NANO. (docs.zephyrproject.org) - To use nano Newlib:
CONFIG_NEWLIB_LIBC=y+CONFIG_NEWLIB_LIBC_NANO=y(if your arch/toolchain provides it). (docs.zephyrproject.org)
CONFIG_REQUIRES_FULL_LIBCPP
A “request” flag used by apps/subsystems to indicate they need a full C++ standard library (i.e., STL, etc.). When set, Zephyr will auto-select a compatible toolchain C++ standard library (unless you explicitly chose one via CONFIG_LIBCPP_IMPLEMENTATION / e.g. CONFIG_GLIBCXX_LIBCPP). (docs.zephyrproject.org)
Common “working” app setup (prj.conf)
# C library
CONFIG_NEWLIB_LIBC=y
# CONFIG_NEWLIB_LIBC_NANO is unset => full newlib
# C++
CONFIG_CPP=y
CONFIG_REQUIRES_FULL_LIBCPP=y
# (alternative: explicitly pick the implementation, e.g. CONFIG_GLIBCXX_LIBCPP=y)
CONFIG_REQUIRES_FULL_LIBCPP does not by itself enable compiling C++ sources—you still need CONFIG_CPP=y. (docs.zephyrproject.org)
Citations:
- 1: https://docs.zephyrproject.org/latest/develop/languages/c/newlib.html?utm_source=openai
- 2: https://docs.zephyrproject.org/latest/develop/languages/c/newlib.html?utm_source=openai
- 3: https://docs.zephyrproject.org/latest/develop/languages/c/newlib.html?utm_source=openai
- 4: https://docs.zephyrproject.org/latest/develop/languages/cpp/index.html?utm_source=openai
- 5: https://docs.zephyrproject.org/latest/develop/languages/cpp/index.html?utm_source=openai
🌐 Web query:
Zephyr CONFIG_NEWLIB_LIBC deprecation 4.3
💡 Result:
In Zephyr v4.3.0 (released 2025-11-14), CONFIG_NEWLIB_LIBC is not deprecated. It is still the Kconfig symbol used to select Newlib as the C library implementation, and it remains one of the options in the LIBC_IMPLEMENTATION choice menu (“C Library Implementation”). [1]
What did change around this area is mostly about defaults/selection flow:
- Zephyr now models libc selection explicitly as a single choice (
LIBC_IMPLEMENTATION), with candidates likeMINIMAL_LIBC,PICOLIBC,NEWLIB_LIBC, etc. [1] - The docs still describe enabling Newlib by setting
CONFIG_NEWLIB_LIBC=y(and optionallyCONFIG_NEWLIB_LIBC_NANO). [2]
If you’re seeing a “deprecation” warning in a 4.3-based build, it’s likely coming from something else in your config (e.g., conflicting libc selections, toolchain capability like TOOLCHAIN_HAS_NEWLIB, or an out-of-tree layer emitting its own warning), not from Zephyr v4.3 deprecating CONFIG_NEWLIB_LIBC itself. [1]
Sources:
[1] Zephyr v4.3.0 lib/libc/Kconfig (LIBC_IMPLEMENTATION choice includes NEWLIB_LIBC) (raw.githubusercontent.com)
[2] Zephyr documentation: “Newlib … enabled by selecting CONFIG_NEWLIB_LIBC” (docs.zephyrproject.org)
Citations:
- 1: https://raw.githubusercontent.com/zephyrproject-rtos/zephyr/v4.3.0/lib/libc/Kconfig
- 2: https://docs.zephyrproject.org/latest/develop/languages/c/newlib.html?utm_source=openai
🌐 Web query:
Zephyr REQUIRES_FULL_LIBCPP C++ standard library configuration
💡 Result:
CONFIG_REQUIRES_FULL_LIBCPP is the Zephyr Kconfig switch used by an application or subsystem to say “I need a complete C++ standard library (STL, etc.), not Zephyr’s minimal C++ support”.
What it does
CONFIG_REQUIRES_FULL_LIBCPP=yforces selection of a full C++ standard library and also selectsCONFIG_REQUIRES_FULL_LIBC(i.e., you’ll also end up with a full C library, not a minimal/nano one). [1]- It implicitly prevents using Zephyr’s minimal C++ library because
MINIMAL_LIBCPPis only allowed when!REQUIRES_FULL_LIBCPP. [1]
How Zephyr chooses which C++ standard library (LIBCPP_IMPLEMENTATION)
Zephyr uses the CONFIG_LIBCPP_IMPLEMENTATION choice to decide what to link:
Defaults when REQUIRES_FULL_LIBCPP=y:
EXTERNAL_LIBCPPifNATIVE_BUILD[1]LIBCXX_LIBCPPif toolchain variant isllvm[1]- otherwise
GLIBCXX_LIBCPP(GNU libstdc++) [1]
Available options in that choice include:
CONFIG_GLIBCXX_LIBCPP(GNU libstdc++), depends onCONFIG_NEWLIB_LIBCorCONFIG_PICOLIBC[1]CONFIG_LIBCXX_LIBCPP(LLVM libc++), depends onCONFIG_NEWLIB_LIBCand LLVM toolchain variant [1]CONFIG_EXTERNAL_LIBCPP(user-provided) [1]
Zephyr’s docs also summarize the intent: components that need the “full” library can select CONFIG_REQUIRES_FULL_LIBCPP, and Zephyr will auto-pick a compatible C++ standard library unless you explicitly pick one. [2]
Practical prj.conf examples
1) “I use STL, pick the right full lib automatically”
CONFIG_CPP=y
CONFIG_REQUIRES_FULL_LIBCPP=y
(Zephyr will default to libstdc++ / libc++ / external depending on build/toolchain.) [1]
2) Force GNU libstdc++
CONFIG_CPP=y
CONFIG_REQUIRES_FULL_LIBCPP=y
CONFIG_GLIBCXX_LIBCPP=y
(You’ll also need a compatible C library selection such as Newlib or Picolibc due to dependencies.) [1]
3) Force LLVM libc++
CONFIG_CPP=y
CONFIG_REQUIRES_FULL_LIBCPP=y
CONFIG_LIBCXX_LIBCPP=y
(Requires LLVM toolchain variant and Newlib.) [1]
If you tell me your toolchain (ZEPHYR_TOOLCHAIN_VARIANT) and libc choice (Newlib/Picolibc/etc.), I can suggest the exact minimal config that will satisfy dependencies. [1]
Sources: [1] [2]
Clarify that CONFIG_REQUIRES_FULL_LIBCPP does not replace CONFIG_NEWLIB_LIBC in Zephyr 4.3.x.
CONFIG_NEWLIB_LIBC is not deprecated in Zephyr 4.3—it remains the mechanism to select Newlib as the C standard library. CONFIG_REQUIRES_FULL_LIBCPP serves a different purpose: it requests automatic selection of a full C++ standard library (not the minimal C++ support). These options are complementary and often used together, not substitutes for each other. The note's wording ("foi substituído") incorrectly suggests one replaced the other, which could mislead readers about configuration requirements.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/ZEPHYR_PORT_PROGRESS.md` around lines 26 - 28, Update the note to stop
saying CONFIG_REQUIRES_FULL_LIBCPP "foi substituido" por CONFIG_NEWLIB_LIBC and
instead explain their relationship: state that CONFIG_NEWLIB_LIBC remains the
option to select Newlib as the C library, while CONFIG_REQUIRES_FULL_LIBCPP
requests selection of a full C++ standard library and is complementary (not a
replacement), and keep the warning about NEWLIB_LIBC conflicting with
EXTERNAL_LIBC in native_sim (Kconfig warnings fatal in 4.3.x) so readers
understand both options may be used together.
| #if defined(__ZEPHYR__) && !defined(CONFIG_ARCH_POSIX) | ||
|
|
||
| MessagePtr allocate_message(); | ||
| void release_message(Message* msg); | ||
|
|
||
| #else | ||
|
|
||
| inline MessagePtr allocate_message() { | ||
| return std::make_shared<Message>(); | ||
| } | ||
|
|
||
| #endif |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider providing release_message on the non-Zephyr path for API symmetry.
The Zephyr branch declares both allocate_message() and release_message(), but the #else branch only defines allocate_message(). Any shared/portable code that calls platform::release_message() will fail to compile on the host path. Adding a no-op or delete-based stub on the non-Zephyr side would make the API unconditionally available.
♻️ Proposed fix
`#else`
inline MessagePtr allocate_message() {
return std::make_shared<Message>();
}
+inline void release_message(Message* /* msg */) {
+ // No-op: shared_ptr handles deletion on non-embedded targets.
+}
+
`#endif`🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@include/platform/memory.h` around lines 31 - 42, The non-Zephyr branch
defines allocate_message() but omits release_message(), breaking API symmetry;
add an inline release_message(Message* msg) stub in the `#else` block (matching
the Zephyr signature) that is a no-op (or forwards to delete if using raw
pointers) so platform::release_message() is always available; ensure the
function uses the same types (MessagePtr/Message) and is declared/defined
alongside allocate_message() for consistency.
| fi | ||
|
|
||
| echo " Starting Renode..." | ||
| renode --disable-xwt -e "\$firmware=@$ELF_PATH; i @$RENODE_SCRIPT; start; sleep 10; quit" 2>&1 |
There was a problem hiding this comment.
Renode quit always exits 0 — test failures are not propagated.
The sleep 10; quit sequence exits Renode regardless of whether the firmware test passed or failed. For test_core, the firmware returns a non-zero exit code on failure, but this is lost because Renode's own exit code from quit is always 0. Consider using Renode's test infrastructure or parsing UART output for PASS/FAIL markers to propagate the result.
Additionally, the hardcoded sleep 10 is fragile: long tests get truncated, short tests waste time.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/run_renode_test.sh` at line 56, The current invocation using renode
... start; sleep 10; quit swallows the firmware exit status because Renode's
quit always returns 0 and the hardcoded sleep 10 is fragile; update the script
that builds the renode command (references: RENODE_SCRIPT, ELF_PATH, the use of
start; sleep 10; quit, and test_core firmware) to either (a) use Renode's
built‑in test infrastructure/`test` commands in the RENODE_SCRIPT so Renode will
emit/pass through a test status, or (b) remove the fixed sleep and instead read
and tail Renode's UART/log output for explicit PASS/FAIL markers and block until
one appears (with a timeout), then propagate a non‑zero exit code on FAIL;
ensure the wrapper script exits with the propagated status from the parsed
marker or test result rather than relying on Renode's quit.
| static char message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)] | ||
| __aligned(8); |
There was a problem hiding this comment.
Use alignof(someip::Message) instead of hardcoded __aligned(8).
Message contains std::vector, std::optional, std::chrono::time_point, and other members whose required alignment may exceed 8 on some architectures. Placement-new on an insufficiently aligned buffer is undefined behavior.
🐛 Proposed fix
-static char message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)]
- __aligned(8);
+static char __aligned(alignof(someip::Message))
+ message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| static char message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)] | |
| __aligned(8); | |
| static char __aligned(alignof(someip::Message)) | |
| message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)]; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/platform/zephyr_memory.cpp` around lines 21 - 22, The static buffer
message_pool_buffer is aligned to a hardcoded 8 bytes which may be insufficient
for someip::Message; change the alignment to use the type's alignment
(alignof(someip::Message)) instead of __aligned(8) so placement-new is
safe—update the declaration of message_pool_buffer to apply alignment based on
alignof(someip::Message) (referencing message_pool_buffer and someip::Message)
using your platform's alignment attribute/macro.
| #include <atomic> | ||
| #include <thread> | ||
| #include <chrono> | ||
| #include "platform/byteorder.h" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check direct includes in sd_server.cpp
echo "=== Direct includes in sd_server.cpp ==="
rg '#include' src/sd/sd_server.cpp
echo -e "\n=== Does platform/byteorder.h transitively include inet or socket headers? ==="
fd byteorder.h --type f | head -1 | xargs cat 2>/dev/null | head -30
echo -e "\n=== Does platform/net.h exist? ==="
fd 'net\.h' --path '*/platform/*' --type f
echo -e "\n=== What does platform/net.h contain? ==="
fd 'net\.h' --path '*/platform/*' --type f | xargs cat 2>/dev/null | head -50
echo -e "\n=== Check what transport headers include ==="
fd 'udp_transport.h' --type f | xargs head -30 2>/dev/null | grep -A 30 '^#include'
echo -e "\n=== Search for inet_addr in platform headers ==="
fd '\.h' --path '*/platform/*' --type f | xargs rg 'inet_addr' 2>/dev/nullRepository: vtz/opensomeip
Length of output: 4015
inet_addr is available via transitive include; explicit include recommended for clarity.
inet_addr is defined as a macro in "platform/net.h", which is pulled in transitively through "transport/udp_transport.h". The code will compile without an explicit include. However, relying on transitive includes is fragile and obscures the actual dependency. For code clarity and maintainability, add an explicit include to "platform/net.h":
Suggested improvement
`#include` "platform/byteorder.h"
+#include "platform/net.h"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #include "platform/byteorder.h" | |
| `#include` "platform/byteorder.h" | |
| `#include` "platform/net.h" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/sd/sd_server.cpp` at line 23, The source uses inet_addr (a macro) without
directly including its header; add an explicit `#include` "platform/net.h" at the
top of sd_server.cpp so the dependency is clear and not reliant on transitive
includes (this makes inet_addr's definition explicit and improves
maintainability).
| auto* offer_entry_ptr = static_cast<ServiceEntry*>(sd_message.get_entries()[0].get()); | ||
| offer_entry_ptr->set_index1(0); // Reference first option | ||
| offer_entry_ptr->set_index2(0); // No second option |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
static_cast on SD entries retrieved after add_entry — correct but consider a helper.
After add_entry(std::move(offer_entry)), the code retrieves it back via get_entries()[0].get() and static_casts to the concrete type. This pattern is duplicated across send_service_offer (lines 365-367) and send_service_offer_to_client (lines 535-537), and also in sd_client.cpp. Since the cast is always to the type just added, it's correct, but the repetition invites a slip if entries are reordered.
Also applies to: 535-537
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/sd/sd_server.cpp` around lines 365 - 367, The code repeatedly retrieves
an entry added via add_entry(...) and does a static_cast on
sd_message.get_entries()[i].get() (seen in send_service_offer,
send_service_offer_to_client and sd_client.cpp), which is correct but duplicated
and brittle; introduce a small helper to centralize the cast—either a template
method like get_entry_as<T>(SdMessage&, size_t idx) or an add_entry variant that
returns the concrete pointer after insertion (e.g.,
add_entry_and_get<T>(std::unique_ptr<T>)), then replace direct static_cast uses
in send_service_offer/send_service_offer_to_client (and sd_client.cpp) with the
helper to ensure the cast is performed in one place and reduce risk of
index/order mistakes.
| if (!local_endpoint_.is_valid()) { | ||
| #if defined(__cpp_exceptions) || defined(__EXCEPTIONS) | ||
| throw std::invalid_argument("Invalid local endpoint"); | ||
| #endif | ||
| } |
There was a problem hiding this comment.
Silent no-op when exceptions are disabled leaves the object in an invalid state.
When __cpp_exceptions is not defined (common on Zephyr), a bad endpoint silently constructs a UdpTransport that will fail later at bind_socket. The caller has no way to detect this.
Consider adding a factory method or an is_valid() / initialization flag that callers can check, or make start() validate the endpoint as well.
Proposed fix — validate in start()
Result UdpTransport::start() {
if (is_running()) {
return Result::SUCCESS;
}
+ if (!local_endpoint_.is_valid()) {
+ return Result::INVALID_ENDPOINT;
+ }
+
Result result = create_socket();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/transport/udp_transport.cpp` around lines 33 - 37, The constructor
currently skips signalling an invalid local_endpoint_ when exceptions are
disabled, leaving UdpTransport in a broken state; update initialization and
lifecycle checks so callers can detect failure: either set an internal bool
(e.g., valid_ or initialized_) when local_endpoint_ is valid in the UdpTransport
constructor and expose is_valid(), or perform the same validation in start()
(before bind_socket) and return/propagate an error if invalid; ensure all code
paths that rely on local_endpoint_ (bind_socket, start) check this flag or
validation and fail fast with a clear error/return code rather than silently
proceeding.
| CONFIG_NET_LOG_LEVEL_INF=y | ||
| CONFIG_NET_SHELL=y |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Gate NET_SHELL behind debug-specific overlays.
CONFIG_NET_SHELL=y is great for bring-up, but enabling it unconditionally increases footprint and runtime exposure.
Proposed change
CONFIG_NET_LOG_LEVEL_INF=y
-CONFIG_NET_SHELL=y
+# Enable NET_SHELL only in debug overlays when needed.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CONFIG_NET_LOG_LEVEL_INF=y | |
| CONFIG_NET_SHELL=y | |
| CONFIG_NET_LOG_LEVEL_INF=y | |
| # Enable NET_SHELL only in debug overlays when needed. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/net_test/prj.conf` around lines 17 - 18, The PR currently
enables CONFIG_NET_SHELL=y unconditionally; restrict it to debug builds by
moving or gating that setting into a debug-specific overlay (e.g., an overlay
file or a config fragment applied only for debug/bring-up), leaving
CONFIG_NET_LOG_LEVEL_INF=y in the base prj.conf; update references to
CONFIG_NET_SHELL so it is only defined in the debug overlay and remove it from
the main prj.conf to avoid increasing footprint and runtime exposure in release
builds.
| CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 | ||
| CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=2 | ||
| CONFIG_NET_MAX_CONTEXTS=10 | ||
| CONFIG_NET_BUF_RX_COUNT=16 | ||
| CONFIG_NET_BUF_TX_COUNT=16 | ||
| CONFIG_NET_PKT_RX_COUNT=8 | ||
| CONFIG_NET_PKT_TX_COUNT=8 | ||
|
|
||
| CONFIG_HEAP_MEM_POOL_SIZE=131072 | ||
| CONFIG_MAIN_STACK_SIZE=4096 |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Move aggressive resource sizing to board-specific overlays.
Fixed counts and large heap/stack values on Line 20-Line 29 can reduce portability across Zephyr targets with tighter RAM limits.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/net_test/prj.conf` around lines 20 - 29, The PR sets
aggressive global Kconfig values (CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT,
CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT, CONFIG_NET_MAX_CONTEXTS,
CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_BUF_TX_COUNT, CONFIG_NET_PKT_RX_COUNT,
CONFIG_NET_PKT_TX_COUNT, CONFIG_HEAP_MEM_POOL_SIZE, CONFIG_MAIN_STACK_SIZE) in
the sample prj.conf which harms portability; remove or revert these hard-coded
high values from this shared sample and instead place them in board-specific
overlay files (or conditional Kconfig fragments) for boards that need larger
resources, ensuring the sample uses conservative defaults or leaves them unset
so targets with tight RAM are not broken.
Resolve 31 issues identified during code review covering thread safety, CI reliability, platform portability, and embedded correctness. Key changes: - Fix lock-order inversion and recursive deadlock in event_publisher - Make Zephyr Thread non-movable with heap-allocated trampoline context - Replace unsafe unaligned reinterpret_cast reads with memcpy in message and e2e deserialization for Cortex-M alignment safety - Add Windows ioctlsocket implementations for nonblocking socket helpers - Remove || true from CI and test scripts so failures are not masked - Add thread-safe slab initialization in zephyr_memory with k_mutex - Harden IPv6 validation to reject :::, leading/trailing single colons - Add Kconfig transport dependencies, range constraints, and default n - Add non-root user to Dockerfile.zephyr - Translate docs/ZEPHYR_PORT_PROGRESS.md to English
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
include/tp/tp_types.h (2)
55-63:⚠️ Potential issue | 🟠 MajorDefault
max_message_size/max_concurrent_transfersare incompatible with Zephyr heap budgets.
TpReassemblyBuffercallsreceived_data.resize(total_length)eagerly on construction (Line 104). Withmax_message_size{1000000}andmax_concurrent_transfers{10}, peak heap from reassembly data alone is ~10 MB — far beyond the RAM of typical Zephyr targets (often 256 KB–512 KB total).Consider:
- Lazy/chunked allocation instead of pre-sizing the full buffer at construction.
- Dramatically lower Zephyr-specific defaults via compile-time config macros (e.g.,
CONFIG_SOMEIP_TP_MAX_MESSAGE_SIZE).- A static pool allocator to bound worst-case usage at build time.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/tp/tp_types.h` around lines 55 - 63, TpConfig's defaults (max_message_size and max_concurrent_transfers) cause TpReassemblyBuffer to eagerly allocate huge buffers because TpReassemblyBuffer calls received_data.resize(total_length) on construction; change this by (1) lowering default values in TpConfig (e.g., max_message_size and max_concurrent_transfers) to Zephyr-safe values or make them driven by compile-time macros (CONFIG_SOMEIP_TP_MAX_MESSAGE_SIZE / CONFIG_SOMEIP_TP_MAX_CONCURRENT_TRANSFERS), and (2) modify TpReassemblyBuffer to avoid eager full-size allocation—use lazy/chunked allocation or a static/pool allocator for received_data (instead of resize(total_length)) so worst-case heap usage is bounded at build time.
57-57:⚠️ Potential issue | 🟡 MinorComment inaccuracy: 1,000,000 bytes is not 1 MB (MiB).
1 MiB = 1,048,576 bytes; 1,000,000 bytes is 1 MB (SI). The comment should read
"(~1 MB default)"or the value should be1048576if MiB was intended.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/tp/tp_types.h` at line 57, The comment for the field max_message_size currently states "1MB default" but the value 1000000 is SI MB not MiB; either change the numeric value to 1048576 if you intended 1 MiB, or (safer) update the comment to "(~1 MB default)" to accurately reflect 1,000,000 bytes—locate the uint32_t max_message_size{1000000}; declaration and update the comment accordingly.
♻️ Duplicate comments (24)
zephyr/boards/s32k388_renode/s32k388_renode.conf (1)
7-10:⚠️ Potential issue | 🟡 Minor
CONFIG_NET_MAX_CONTEXTSnot set — SD's multicast + unicast sockets may exhaust the default limit.The default
CONFIG_NET_MAX_CONTEXTSin Zephyr is typically 6. SOME/IP SD opens both a multicast and a unicast socket simultaneously; combined with application-level sockets, this can silently exhaust the pool at runtime.🛠️ Proposed fix
CONFIG_NET_SOCKETS=y +CONFIG_NET_MAX_CONTEXTS=16🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/boards/s32k388_renode/s32k388_renode.conf` around lines 7 - 10, The board configuration is missing an explicit CONFIG_NET_MAX_CONTEXTS override so SOME/IP Service Discovery (which opens both multicast and unicast sockets) plus app sockets can exhaust the default socket context pool; update the s32k388_renode config to set CONFIG_NET_MAX_CONTEXTS to a higher value (e.g., 8 or 10) to accommodate SD's multicast and unicast sockets and any application sockets, ensuring the change appears alongside the existing network configs (referencing CONFIG_NETWORKING, CONFIG_NET_IPV4, CONFIG_NET_UDP, CONFIG_NET_SOCKETS).zephyr/samples/hello_s32k/prj.conf (1)
6-6:⚠️ Potential issue | 🟡 Minor
CONFIG_MAIN_STACK_SIZE=2048remains unchanged and is likely insufficient.All other SOME/IP samples in this PR use 8192. At 2 KiB, C++17 global static constructors and the full libcpp runtime initialisation can exhaust the stack, producing a hard fault at boot.
🛠️ Proposed fix
-CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_MAIN_STACK_SIZE=8192🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/hello_s32k/prj.conf` at line 6, Update the CONFIG_MAIN_STACK_SIZE setting in prj.conf from 2048 to 8192 to match the other SOME/IP samples; modify the CONFIG_MAIN_STACK_SIZE entry so the main thread stack size is increased to 8192 (so look for the CONFIG_MAIN_STACK_SIZE key and change its value).scripts/run_zephyr_tests.sh (1)
51-55:⚠️ Potential issue | 🟠 MajorNão engula falhas de runtime no
native_sim.Com
|| true, o teste é marcado como aprovado mesmo quando falha.✅ Ajuste sugerido
- timeout 30 "$build_dir/zephyr/zephyr.exe" 2>&1 || true - PASSED=$((PASSED + 1)) + if timeout 30 "$build_dir/zephyr/zephyr.exe" 2>&1; then + PASSED=$((PASSED + 1)) + else + echo " Run: FAILED" + FAILED=$((FAILED + 1)) + fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/run_zephyr_tests.sh` around lines 51 - 55, The test runner currently swallows runtime failures for the native_sim case by appending "|| true" to the timeout invocation, causing PASSED to be incremented regardless; remove "|| true", capture the exit status of "$build_dir/zephyr/zephyr.exe" (or the timeout command) and only increment PASSED when the command exits with 0 (e.g., store the exit code from the timeout call and check it before updating PASSED), keeping the printf and timeout usage intact.include/platform/thread.h (4)
97-97:⚠️ Potential issue | 🔴 Critical
~Thread() = defaultpode liberar stack com thread ainda em execução.Se o objeto for destruído sem
join(), há risco de use-after-free da stack registrada no kernel.🐛 Ajuste sugerido
- ~Thread() = default; + ~Thread() { + if (joinable()) { + k_thread_abort(&thread_); + joined_ = true; + } + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` at line 97, O destrutor atual ~Thread() = default pode destruir o objeto enquanto a thread subjacente ainda está em execução; altere o destrutor da classe Thread para não liberar recursos sem tratamento: dentro de Thread::~Thread() verifique se a thread está joinable (usar o método joinable() ou o campo que indica estado) e em caso afirmativo chamar join() ou abortar/terminar explicitamente (por exemplo std::terminate()) para evitar use-after-free da stack do kernel; garanta também que Thread::join() exista e seja usado pelo código chamador quando for apropriado.
92-94:⚠️ Potential issue | 🔴 CriticalUse
K_THREAD_STACK_SIZEOF(stack_)em vez desizeof(stack_).O tamanho passado ao
k_thread_createdeve ser o tamanho utilizável da stack Zephyr, nãosizeofbruto.🐛 Ajuste sugerido
- k_thread_create(&thread_, stack_, sizeof(stack_), + k_thread_create(&thread_, stack_, K_THREAD_STACK_SIZEOF(stack_), trampoline, this, nullptr, nullptr, K_PRIO_PREEMPT(7), 0, K_NO_WAIT);According to Zephyr docs, what stack_size should be passed to k_thread_create when using K_THREAD_STACK_MEMBER/K_THREAD_STACK_DEFINE?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 92 - 94, Substitua o uso de sizeof(stack_) ao chamar k_thread_create pelo tamanho utilizável fornecido por K_THREAD_STACK_SIZEOF(stack_); ou seja, na chamada k_thread_create(&thread_, stack_, sizeof(stack_), trampoline, this, nullptr, nullptr, K_PRIO_PREEMPT(7), 0, K_NO_WAIT) troque sizeof(stack_) por K_THREAD_STACK_SIZEOF(stack_) para que o argumento de tamanho da stack_ seja correto ao usar K_THREAD_STACK_MEMBER/K_THREAD_STACK_DEFINE.
29-31:⚠️ Potential issue | 🟡 MinorInclua
<chrono>explicitamente e evite truncamento emsleep_for.O header usa
std::chronosem include direto e faz cast paraint32_tsem proteção de faixa.Also applies to: 187-190
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 29 - 31, Add an explicit `#include` <chrono> to include/platform/thread.h and replace any raw int32_t casts around sleep_for with chrono-safe conversions: use std::chrono::duration_cast<std::chrono::milliseconds>(your_duration) (or construct std::chrono::milliseconds directly) and pass that duration to std::this_thread::sleep_for instead of casting to int32_t; if you must convert to an integral count, clamp to the valid range (e.g. std::min/max with INT32_MAX) before casting to avoid truncation.
108-127:⚠️ Potential issue | 🔴 CriticalMove ctor/assignment estão incorretos para
k_thread.Copiar
k_thread/stack commemcpye mover apóstrampolineter recebidothisquebra invariantes do kernel e pode descartar a execução real da entry function.🛠️ Correção mínima segura
- Thread(Thread&& o) noexcept - : entry_(std::move(o.entry_)), joined_(o.joined_) { - std::memcpy(&thread_, &o.thread_, sizeof(thread_)); - std::memcpy(stack_, o.stack_, sizeof(stack_)); - o.entry_ = nullptr; - o.joined_ = true; - } - - Thread& operator=(Thread&& o) noexcept { - if (this != &o) { - if (joinable()) join(); - entry_ = std::move(o.entry_); - joined_ = o.joined_; - std::memcpy(&thread_, &o.thread_, sizeof(thread_)); - std::memcpy(stack_, o.stack_, sizeof(stack_)); - o.entry_ = nullptr; - o.joined_ = true; - } - return *this; - } + Thread(Thread&&) = delete; + Thread& operator=(Thread&&) = delete;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 108 - 127, A move ctor/operator currently memcpy's k_thread and stack while the kernel trampoline may still reference the original Thread (via trampoline using this), which breaks kernel invariants; before copying thread_/stack in Thread(Thread&&) and operator=(Thread&&) ensure the source is not active: if o.joinable() call o.join() (or otherwise assert/return error) so the thread has finished and the kernel no longer references its stack/trampoline, then perform std::memcpy of thread_ and stack_ and transfer entry_/joined_ (and null out o.entry_/set o.joined_). Also ensure you avoid memcpy when the source is still joinable to prevent discarding a running entry function.zephyr/samples/net_test/prj.conf (2)
20-29:⚠️ Potential issue | 🟠 MajorSizing global agressivo reduz portabilidade do sample.
Esses valores fixos de buffers/heap/stack podem quebrar alvos com RAM menor. Mova para overlays por board e deixe o
prj.confbase mais conservador.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/net_test/prj.conf` around lines 20 - 29, O prj.conf define valores de recurso agressivos que podem quebrar boards com menos RAM; altere o prj.conf removendo ou reduzindo as chaves CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT, CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT, CONFIG_NET_MAX_CONTEXTS, CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_BUF_TX_COUNT, CONFIG_NET_PKT_RX_COUNT, CONFIG_NET_PKT_TX_COUNT, CONFIG_HEAP_MEM_POOL_SIZE e CONFIG_MAIN_STACK_SIZE para valores conservadores/omita-os no prj.conf base, e mova os valores específicos e maiores para overlays por placa (board overlays) para cada target que precise desses limites maiores.
18-18:⚠️ Potential issue | 🟡 MinorEvite
CONFIG_NET_SHELL=ynoprj.confbase do sample.Isso aumenta footprint/superfície em builds não-debug; mantenha em overlay de debug/bring-up.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/net_test/prj.conf` at line 18, Remova a linha CONFIG_NET_SHELL=y do prj.conf base do sample para evitar aumentar footprint em builds não-debug; em vez disso adicione essa configuração apenas ao overlay de bring‑up/debug (por exemplo um arquivo de overlay de debug usado no bring‑up) para que CONFIG_NET_SHELL seja ativado somente em builds de depuração e não no prj.conf principal.docs/ZEPHYR_PORT_PROGRESS.md (2)
6-6:⚠️ Potential issue | 🟡 MinorPadronize “Targets/target” para português.
Ainda há uso de estrangeirismo em um documento predominantemente em português.
Also applies to: 304-304
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/ZEPHYR_PORT_PROGRESS.md` at line 6, Padronize o uso de termos para português trocando todas as ocorrências do cabeçalho/termo "Targets" e quaisquer instâncias de "target" no documento pelo equivalente em português (por exemplo "Alvos" no cabeçalho e "alvo" quando em frase), atualize o plural/singular conforme o contexto e garanta consistência em todas as menções duplicadas (incluindo a ocorrência mostrada com "native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388)"); verifique e atualize também outras ocorrências semelhantes no documento para evitar mistura de inglês e português.
26-28:⚠️ Potential issue | 🟠 MajorCorrija a relação entre
CONFIG_NEWLIB_LIBCeCONFIG_REQUIRES_FULL_LIBCPP.A redação atual indica substituição, mas os símbolos têm papéis diferentes e complementares (C library vs full C++ library). Isso pode levar a configuração incorreta do projeto.
✏️ Sugestão
-> **Nota (Zephyr 4.3.x)**: `CONFIG_NEWLIB_LIBC` foi substituido por -> `CONFIG_REQUIRES_FULL_LIBCPP=y`. Na `native_sim`, `NEWLIB_LIBC` conflita com +> **Nota (Zephyr 4.3.x)**: `CONFIG_NEWLIB_LIBC` continua sendo a selecao da libc +> (Newlib), enquanto `CONFIG_REQUIRES_FULL_LIBCPP=y` solicita uma lib C++ completa. +> Na `native_sim`, `NEWLIB_LIBC` conflita com > `EXTERNAL_LIBC` (Kconfig warnings sao fatais em 4.3.x).In Zephyr 4.3.x, does CONFIG_REQUIRES_FULL_LIBCPP replace CONFIG_NEWLIB_LIBC, or are they complementary options?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/ZEPHYR_PORT_PROGRESS.md` around lines 26 - 28, A frase atual diz que CONFIG_NEWLIB_LIBC foi substituído por CONFIG_REQUIRES_FULL_LIBCPP — corrija para explicar que esses símbolos são complementares: preserve que CONFIG_NEWLIB_LIBC controla a seleção da libc (newlib) enquanto CONFIG_REQUIRES_FULL_LIBCPP solicita uma implementação completa de C++ runtime; atualize o texto na seção que menciona native_sim, NEWLIB_LIBC e EXTERNAL_LIBC para indicar que em Zephyr 4.3.x há conflito entre NEWLIB_LIBC e EXTERNAL_LIBC e que Kconfig warnings são fatais, e reformule a nota para evitar afirmar substituição, deixando claro o propósito distinto de CONFIG_NEWLIB_LIBC versus CONFIG_REQUIRES_FULL_LIBCPP..github/workflows/zephyr.yml (3)
32-33:⚠️ Potential issue | 🟠 MajorValide checksum dos artefatos baixados antes de extrair.
Os downloads de SDK/toolchain sem verificação de integridade deixam risco de supply chain.
Also applies to: 69-72
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 32 - 33, The workflow currently downloads and extracts zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz with wget and tar without verifying integrity; update the steps around the wget/tar commands for zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz (and the analogous block at lines 69-72) to also fetch the corresponding checksum (or .sha256/.sha512) and its signature when available, verify the checksum locally using sha256sum/sha512sum (and optionally gpg verify the signature), and abort the job if the checksum verification fails so extraction (tar xf) only runs after a successful integrity check.
44-44:⚠️ Potential issue | 🟠 MajorNão masque falhas de execução com
|| true.Hoje os jobs passam mesmo com binário falhando/timeout, invalidando o sinal de CI.
✅ Ajuste sugerido
- timeout 30 build/ns_tc/zephyr/zephyr.exe || true + timeout 30 build/ns_tc/zephyr/zephyr.exe ... - timeout 30 build/ns_tp/zephyr/zephyr.exe || true + timeout 30 build/ns_tp/zephyr/zephyr.exe ... - timeout 30 build/ns_echo/zephyr/zephyr.exe || true + timeout 30 build/ns_echo/zephyr/zephyr.exeAlso applies to: 49-49, 54-54
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml at line 44, Remova o "|| true" que está mascarando falhas nos comandos de execução (por exemplo a linha contendo "timeout 30 build/ns_tc/zephyr/zephyr.exe || true") — localizar todas as ocorrências idênticas (também nas outras linhas semelhantes) e simplesmente executar "timeout 30 build/ns_tc/zephyr/zephyr.exe" para que o passo do workflow falhe quando o binário der erro ou timeout; não substitua por silenciadores, mantenha o comportamento padrão de falha do job (ou use explicitamente continue-on-error: true somente se quiser permitir falha).
2-8:⚠️ Potential issue | 🟡 MinorNormalize quoting/spacing para zerar erros de actionlint/yamllint.
Há erros de lint ativos (flow collections com espaçamento e expansão shell sem citação em
-j$(nproc)).Also applies to: 19-19, 25-25, 41-41, 46-46, 51-51, 56-56, 62-62, 80-80
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 2 - 8, Normalize YAML flow-collection spacing and quoting for keys like branches and paths-ignore (ensure items are quoted and there is a single space after colons and commas inside the [ ... ] arrays) and quote any shell expansions such as -j$(nproc) (e.g. change to a quoted string like "-j$(nproc)" or otherwise wrap the expansion in quotes) so actionlint/yamllint no longer flags flow-collection spacing and unquoted shell expansions; update occurrences referenced (branches, paths-ignore, and the -j$(nproc) instances) across the file.scripts/run_renode_test.sh (1)
56-56:⚠️ Potential issue | 🟠 MajorA execução atual do Renode não propaga falha do firmware.
start; sleep 10; quittende a retornar sucesso do Renode, não do teste embarcado. Isso pode gerar falso positivo.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/run_renode_test.sh` at line 56, O comando atual que executa renode (a linha que usa renode --disable-xwt -e "\$firmware=@$ELF_PATH; i @$RENODE_SCRIPT; start; sleep 10; quit") não propaga o resultado do teste embarcado; altere a execução para capturar a saída do Renode (stdout/stderr) e avaliar o status do teste (por exemplo procurando tokens de sucesso/falha emitidos pelo firmware ou pelo script de monitor), e então retornar esse status no script (ou seja, executar renode, salvar sua saída em uma variável/arquivo, avaliar presença de "PASS"/"FAIL" ou o token usado pelo test harness e usar exit <code> apropriado); referencie a invocação que contém $ELF_PATH e $RENODE_SCRIPT e garanta que o script retorne não-zero em caso de falha detectada em vez de confiar no sucesso do próprio processo renode.include/platform/net.h (1)
121-133:⚠️ Potential issue | 🔴 CriticalWindows is missing
someip_set_nonblocking/someip_set_blockinghelpers.
someip_set_nonblocking()is used by shared transport code, but Line 122 only defines these helpers for non-Windows builds. This breaks Windows compilation paths.🛠️ Proposed fix
-/* Portable non-blocking mode */ -#if !defined(_WIN32) +/* Portable non-blocking mode */ +#if defined(_WIN32) +static inline int someip_set_nonblocking(int fd) { + u_long mode = 1; + return ioctlsocket(static_cast<SOCKET>(fd), FIONBIO, &mode) == 0 ? 0 : -1; +} +static inline int someip_set_blocking(int fd) { + u_long mode = 0; + return ioctlsocket(static_cast<SOCKET>(fd), FIONBIO, &mode) == 0 ? 0 : -1; +} +#else static inline int someip_set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags < 0) return -1; return fcntl(fd, F_SETFL, flags | O_NONBLOCK); } static inline int someip_set_blocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags < 0) return -1; return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); } `#endif`#!/bin/bash set -euo pipefail echo "== net.h helper definitions ==" rg -n "someip_set_nonblocking|someip_set_blocking|_WIN32" include/platform/net.h -C2 echo echo "== call sites in transport code ==" rg -n "\bsomeip_set_nonblocking\s*\(|\bsomeip_set_blocking\s*\(" src include -g '*.{h,c,cc,cpp,hpp}'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/net.h` around lines 121 - 133, The helpers someip_set_nonblocking(int fd) and someip_set_blocking(int fd) are only defined for non-Windows builds and break Windows compilation; add equivalent implementations under the `#if` defined(_WIN32) branch that call the WinSock API (use u_long mode = 1; ioctlsocket(fd, FIONBIO, &mode) for non-blocking and mode = 0 for blocking) and return 0 on success / SOCKET_ERROR as -1, ensuring the functions are named someip_set_nonblocking and someip_set_blocking to match call sites and that winsock2.h is included where necessary.zephyr/tests/test_transport/src/main.cpp (2)
52-53:⚠️ Potential issue | 🟠 MajorReceive path is flaky without bounded wait and fail-fast exits.
After failed
start()/send_message(), the test continues, and Line 74 performs only one receive attempt after a fixed sleep. This can cause intermittent failures.🔧 Suggested fix
auto result = server.start(); CHECK(result == Result::SUCCESS, "server_start"); + if (result != Result::SUCCESS) return; @@ result = client.start(); CHECK(result == Result::SUCCESS, "client_start"); + if (result != Result::SUCCESS) return; @@ result = client.send_message(msg, bound_ep); CHECK(result == Result::SUCCESS, "send_message"); + if (result != Result::SUCCESS) return; @@ - platform::this_thread::sleep_for(std::chrono::milliseconds(100)); - - auto received = server.receive_message(); + auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(1); + auto received = server.receive_message(); + while (!received && std::chrono::steady_clock::now() < deadline) { + platform::this_thread::sleep_for(std::chrono::milliseconds(10)); + received = server.receive_message(); + } CHECK(received != nullptr, "receive_message");Also applies to: 66-67, 69-75
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_transport/src/main.cpp` around lines 52 - 53, The test continues after failures and performs only a single receive attempt causing flakiness; make the test fail-fast and add a bounded receive loop: after calling server.start() and the subsequent server.send_message(), check their Result values and immediately abort/return the test on non-success (replace or augment CHECK(result == Result::SUCCESS, "server_start") and the send_message CHECKs with an early exit on failure), and replace the single receive attempt at the later line (the lone receive/receive_message call) with a bounded retry loop that waits up to a configured timeout/attempt count (with short sleeps/backoff) before failing so the receive path is deterministic.
47-47:⚠️ Potential issue | 🟠 MajorHard-coded loopback address makes the test environment-dependent.
Line 47 and Line 64 pin to
127.0.0.1, which is brittle on Zephyr native_sim/TAP unless loopback is explicitly enabled.🔧 Suggested fix
- Endpoint server_ep("127.0.0.1", 0); + Endpoint server_ep(CONFIG_NET_CONFIG_MY_IPV4_ADDR, 0); @@ - Endpoint client_ep("127.0.0.1", 0); + Endpoint client_ep(CONFIG_NET_CONFIG_MY_IPV4_ADDR, 0);Also applies to: 64-64
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_transport/src/main.cpp` at line 47, Replace the hard-coded loopback addresses used when constructing Endpoint objects: instead of Endpoint server_ep("127.0.0.1", 0) bind the server to all interfaces (e.g. "0.0.0.0" or the library's IPv4-any constant) so tests do not depend on loopback being enabled, and avoid using the literal "127.0.0.1" for the client; have the client use the actual server address/port (e.g. obtain the bound port from server_ep and construct client Endpoint from server_ep.address()/port or resolve "localhost" via getaddrinfo) — update the constructors referencing Endpoint, server_ep and any client_ep usage accordingly.src/transport/udp_transport.cpp (1)
34-36:⚠️ Potential issue | 🟠 MajorNo-exception builds still allow invalid endpoint construction.
Line 34–36 only throws when exceptions are enabled; otherwise the object can enter an invalid state and fail later in less obvious ways.
🔧 Suggested fix (fail fast in lifecycle)
Result UdpTransport::start() { if (is_running()) { return Result::SUCCESS; } + + if (!local_endpoint_.is_valid()) { + return Result::INVALID_ENDPOINT; + } Result result = create_socket();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/udp_transport.cpp` around lines 34 - 36, The constructor code in udp_transport.cpp that currently conditionally throws "Invalid local endpoint" when exceptions are enabled can leave objects invalid in no-exceptions builds; change the failure path so we fail fast in all builds: either (A) replace the `#if` block with an unconditional abort/terminate call (e.g., std::terminate() or std::abort()) so construction never produces an invalid object when exceptions are disabled, or (B) convert the constructor into a factory (e.g., static create(...) returning std::optional or a Result) or set an explicit m_valid flag and prevent usage elsewhere; locate the conditional throw (the "Invalid local endpoint" check inside the UDP transport constructor/creation code) and implement one of these consistent failure strategies so no-invalid-instance can be created.include/platform/memory.h (1)
36-42: 🛠️ Refactor suggestion | 🟠 MajorExpose
release_message()on non-Zephyr builds for API symmetry.The
#elsebranch definesallocate_message()but omitsrelease_message(). Portable code that callsplatform::release_message()won’t compile on host/native builds.♻️ Suggested fix
`#else` inline MessagePtr allocate_message() { return std::make_shared<Message>(); } +inline void release_message(Message* /* msg */) { + // no-op on host/native: shared_ptr owns lifetime +} + `#endif`🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/memory.h` around lines 36 - 42, The non-Zephyr branch defines allocate_message() but omits release_message(), breaking calls to platform::release_message() on host builds; add a matching inline release_message(MessagePtr msg) in the `#else` block that mirrors the Zephyr API (e.g., accepts a MessagePtr and releases/reset it appropriately) so API symmetry is preserved with allocate_message(), referencing MessagePtr, Message, allocate_message(), and release_message() in the same header.src/platform/zephyr_memory.cpp (2)
26-32:⚠️ Potential issue | 🟠 MajorMake slab initialization thread-safe.
slab_initializedis unsynchronized; concurrentallocate_message()can race and double-init the slab.🔒 Suggested fix
static struct k_mem_slab message_slab; static bool slab_initialized = false; +K_MUTEX_DEFINE(message_slab_init_mutex); static void ensure_slab_init() { if (!slab_initialized) { - k_mem_slab_init(&message_slab, message_pool_buffer, - sizeof(someip::Message), - CONFIG_SOMEIP_MESSAGE_POOL_SIZE); - slab_initialized = true; + k_mutex_lock(&message_slab_init_mutex, K_FOREVER); + if (!slab_initialized) { + k_mem_slab_init(&message_slab, message_pool_buffer, + sizeof(someip::Message), + CONFIG_SOMEIP_MESSAGE_POOL_SIZE); + slab_initialized = true; + } + k_mutex_unlock(&message_slab_init_mutex); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/platform/zephyr_memory.cpp` around lines 26 - 32, ensure_slab_init can race because slab_initialized is unsynchronized; make slab initialization thread-safe by using a synchronization primitive (e.g., a mutex, spinlock, or atomic) to perform a double-checked init: in allocate_message() or ensure_slab_init() first check slab_initialized, if false acquire the lock, check slab_initialized again, then call k_mem_slab_init(&message_slab, message_pool_buffer, sizeof(someip::Message), CONFIG_SOMEIP_MESSAGE_POOL_SIZE) and set slab_initialized = true before releasing the lock; reference symbols: ensure_slab_init, slab_initialized, allocate_message, message_slab, message_pool_buffer, k_mem_slab_init, CONFIG_SOMEIP_MESSAGE_POOL_SIZE.
21-22: 🛠️ Refactor suggestion | 🟠 MajorUse type-based alignment instead of hardcoded
8.At Line 21-Line 22, hardcoding
__aligned(8)is fragile for placement-new ofsomeip::Message; usealignof(someip::Message).♻️ Suggested fix
-static char message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)] - __aligned(8); +static char message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)] + __aligned(alignof(someip::Message));#!/bin/bash # Verify current alignment usage in the Zephyr allocator. rg -n 'message_pool_buffer|__aligned\(' src/platform/zephyr_memory.cpp🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/platform/zephyr_memory.cpp` around lines 21 - 22, Replace the hardcoded __aligned(8) on the message_pool_buffer declaration with a type-based alignment using someip::Message's alignment (e.g., use alignas(alignof(someip::Message)) on the static char message_pool_buffer[...] so storage is properly aligned for placement-new of someip::Message); update the declaration that references message_pool_buffer and ensure the alignment expression references someip::Message to avoid magic constants.src/transport/tcp_transport.cpp (1)
207-212:⚠️ Potential issue | 🟠 MajorHandle failures when toggling listen-socket blocking mode.
Line 207 and Line 211 still ignore return values. If restoring non-blocking fails, the accept loop can stall in blocking mode.
🛠 Suggested fix
- someip_set_blocking(listen_socket_fd_); + if (someip_set_blocking(listen_socket_fd_) < 0) { + return -1; + } int client_fd = accept(listen_socket_fd_, (sockaddr*)&client_addr, &client_len); - someip_set_nonblocking(listen_socket_fd_); + if (someip_set_nonblocking(listen_socket_fd_) < 0) { + if (client_fd >= 0) { + someip_close_socket(client_fd); + } + return -1; + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/tcp_transport.cpp` around lines 207 - 212, Check and handle return values of someip_set_blocking(listen_socket_fd_) and someip_set_nonblocking(listen_socket_fd_) around the accept call: if someip_set_blocking fails, log the error and skip the accept attempt (or retry) instead of proceeding; after accept, if someip_set_nonblocking fails, log the failure, attempt a fallback to restore non-blocking mode (e.g., via fcntl) and if that also fails close listen_socket_fd_ (or break out of the accept loop) to avoid leaving the loop in blocking mode; ensure any opened client_fd is closed on error to avoid leaks.src/sd/sd_server.cpp (1)
282-282: Sameplatform::Threadtemporary-move hazard already raised.Line 282 repeats the same pattern reported in
src/transport/tcp_transport.cpp(constructor-started thread moved from temporary).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/sd/sd_server.cpp` at line 282, The member offer_timer_thread_ is being initialized by moving from a temporary platform::Thread created inline (platform::Thread([this]() { ... })), which risks a temporary-move/hazard; fix it by creating a named local platform::Thread variable (e.g., platform::Thread t([this]() { ... });) and then assign/move it into offer_timer_thread_ (offer_timer_thread_ = std::move(t);) or construct offer_timer_thread_ in the initializer list instead—refer to the symbol offer_timer_thread_ and platform::Thread to locate and apply this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/sd/sd_server.cpp`:
- Line 202: The multicast port is being pre-byte-swapped before serialization
which causes double swapping; update the call at multicast_option->set_port to
pass the host-order value directly (use config_.multicast_port without wrapping
in someip_htons) so that the existing serialize() logic performs the correct
byte-order conversion; locate the multicast_option->set_port invocation in
sd_server.cpp and remove the someip_htons() wrapper, keeping the rest of the
serialize() path unchanged.
In `@src/transport/tcp_transport.cpp`:
- Around line 579-580: Replace the direct std::make_shared<Message>() allocation
with the platform/Zephyr-aware message allocator so the hot path uses the
platform allocator; locate the allocation of message (currently message =
std::make_shared<Message>()) and call the platform allocator factory (e.g.,
platform::allocMessage() or the project’s
MessageFactory/PlatformMessageAllocator) to obtain the shared/owned Message
instance, preserve the existing null check and the call to
message->deserialize(message_data), and ensure the returned object type and
ownership semantics match the rest of the code.
- Around line 141-144: The member threads (receive_thread_ and
connection_thread_ in TcpTransport, and the thread member in SD server) are
being initialized by constructing temporary platform::Thread objects and
move-assigning them, which leads to a use-after-free because the kernel thread
stores a pointer to the temporary; fix by constructing the platform::Thread
directly into the member or by move-constructing from a moved temporary so the
kernel sees the correct address: replace the temporary move-assignment pattern
around TcpTransport::receive_loop and TcpTransport::connection_monitor_loop (and
the analogous thread creation in the SD server) with direct in-place
construction of the member thread (or use std::move(platform::Thread(...)) if
necessary) so the created thread context points to the stable member object
instead of a destroyed temporary.
In `@zephyr/CMakeLists.txt`:
- Around line 89-95: The block redundantly re-checks CONFIG_SOMEIP using
zephyr_library_sources_ifdef inside an outer if(CONFIG_SOMEIP) guard; replace
the inner zephyr_library_sources_ifdef(CONFIG_SOMEIP ...) call with
zephyr_library_sources(...) so the sources
${SOMEIP_SRC}/platform/zephyr_thread.cpp and
${SOMEIP_SRC}/platform/zephyr_memory.cpp are added unconditionally within the
already-true CONFIG_SOMEIP branch (modify the invocation of
zephyr_library_sources_ifdef to zephyr_library_sources in that block).
In `@zephyr/samples/someip_echo/prj.conf`:
- Around line 17-18: The project-wide prj.conf must retain the SOMEIP-required
memory settings rather than removing or relocating them; ensure
CONFIG_HEAP_MEM_POOL_SIZE=131072 and CONFIG_MAIN_STACK_SIZE=8192 remain in
prj.conf (used by SOMEIP samples like someip_echo, someip_client, someip_server,
sd_client) or, if you refactor to board overlays, duplicate those exact settings
into every board-specific overlay so all SOMEIP samples continue to receive the
same baseline values.
- Around line 14-15: The prj.conf currently hard-codes network addresses via
CONFIG_NET_CONFIG_MY_IPV4_ADDR and CONFIG_NET_CONFIG_PEER_IPV4_ADDR which
reduces reusability; refactor by removing these fixed values from prj.conf and
instead load them via board- or environment-specific overlays (e.g., board
overlay Kconfig fragments or devicetree/overlay files) or via
CI/runtime-provided build variables so different targets can supply addresses
without editing the sample; update documentation/comments near prj.conf to
explain how to override these configs at build/runtime.
---
Outside diff comments:
In `@include/tp/tp_types.h`:
- Around line 55-63: TpConfig's defaults (max_message_size and
max_concurrent_transfers) cause TpReassemblyBuffer to eagerly allocate huge
buffers because TpReassemblyBuffer calls received_data.resize(total_length) on
construction; change this by (1) lowering default values in TpConfig (e.g.,
max_message_size and max_concurrent_transfers) to Zephyr-safe values or make
them driven by compile-time macros (CONFIG_SOMEIP_TP_MAX_MESSAGE_SIZE /
CONFIG_SOMEIP_TP_MAX_CONCURRENT_TRANSFERS), and (2) modify TpReassemblyBuffer to
avoid eager full-size allocation—use lazy/chunked allocation or a static/pool
allocator for received_data (instead of resize(total_length)) so worst-case heap
usage is bounded at build time.
- Line 57: The comment for the field max_message_size currently states "1MB
default" but the value 1000000 is SI MB not MiB; either change the numeric value
to 1048576 if you intended 1 MiB, or (safer) update the comment to "(~1 MB
default)" to accurately reflect 1,000,000 bytes—locate the uint32_t
max_message_size{1000000}; declaration and update the comment accordingly.
---
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 32-33: The workflow currently downloads and extracts
zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz with wget and tar without
verifying integrity; update the steps around the wget/tar commands for
zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz (and the analogous block at lines
69-72) to also fetch the corresponding checksum (or .sha256/.sha512) and its
signature when available, verify the checksum locally using sha256sum/sha512sum
(and optionally gpg verify the signature), and abort the job if the checksum
verification fails so extraction (tar xf) only runs after a successful integrity
check.
- Line 44: Remova o "|| true" que está mascarando falhas nos comandos de
execução (por exemplo a linha contendo "timeout 30 build/ns_tc/zephyr/zephyr.exe
|| true") — localizar todas as ocorrências idênticas (também nas outras linhas
semelhantes) e simplesmente executar "timeout 30 build/ns_tc/zephyr/zephyr.exe"
para que o passo do workflow falhe quando o binário der erro ou timeout; não
substitua por silenciadores, mantenha o comportamento padrão de falha do job (ou
use explicitamente continue-on-error: true somente se quiser permitir falha).
- Around line 2-8: Normalize YAML flow-collection spacing and quoting for keys
like branches and paths-ignore (ensure items are quoted and there is a single
space after colons and commas inside the [ ... ] arrays) and quote any shell
expansions such as -j$(nproc) (e.g. change to a quoted string like "-j$(nproc)"
or otherwise wrap the expansion in quotes) so actionlint/yamllint no longer
flags flow-collection spacing and unquoted shell expansions; update occurrences
referenced (branches, paths-ignore, and the -j$(nproc) instances) across the
file.
In `@docs/ZEPHYR_PORT_PROGRESS.md`:
- Line 6: Padronize o uso de termos para português trocando todas as ocorrências
do cabeçalho/termo "Targets" e quaisquer instâncias de "target" no documento
pelo equivalente em português (por exemplo "Alvos" no cabeçalho e "alvo" quando
em frase), atualize o plural/singular conforme o contexto e garanta consistência
em todas as menções duplicadas (incluindo a ocorrência mostrada com "native_sim,
mr_canhubk3 (S32K344), s32k388_renode (S32K388)"); verifique e atualize também
outras ocorrências semelhantes no documento para evitar mistura de inglês e
português.
- Around line 26-28: A frase atual diz que CONFIG_NEWLIB_LIBC foi substituído
por CONFIG_REQUIRES_FULL_LIBCPP — corrija para explicar que esses símbolos são
complementares: preserve que CONFIG_NEWLIB_LIBC controla a seleção da libc
(newlib) enquanto CONFIG_REQUIRES_FULL_LIBCPP solicita uma implementação
completa de C++ runtime; atualize o texto na seção que menciona native_sim,
NEWLIB_LIBC e EXTERNAL_LIBC para indicar que em Zephyr 4.3.x há conflito entre
NEWLIB_LIBC e EXTERNAL_LIBC e que Kconfig warnings são fatais, e reformule a
nota para evitar afirmar substituição, deixando claro o propósito distinto de
CONFIG_NEWLIB_LIBC versus CONFIG_REQUIRES_FULL_LIBCPP.
In `@include/platform/memory.h`:
- Around line 36-42: The non-Zephyr branch defines allocate_message() but omits
release_message(), breaking calls to platform::release_message() on host builds;
add a matching inline release_message(MessagePtr msg) in the `#else` block that
mirrors the Zephyr API (e.g., accepts a MessagePtr and releases/reset it
appropriately) so API symmetry is preserved with allocate_message(), referencing
MessagePtr, Message, allocate_message(), and release_message() in the same
header.
In `@include/platform/net.h`:
- Around line 121-133: The helpers someip_set_nonblocking(int fd) and
someip_set_blocking(int fd) are only defined for non-Windows builds and break
Windows compilation; add equivalent implementations under the `#if`
defined(_WIN32) branch that call the WinSock API (use u_long mode = 1;
ioctlsocket(fd, FIONBIO, &mode) for non-blocking and mode = 0 for blocking) and
return 0 on success / SOCKET_ERROR as -1, ensuring the functions are named
someip_set_nonblocking and someip_set_blocking to match call sites and that
winsock2.h is included where necessary.
In `@include/platform/thread.h`:
- Line 97: O destrutor atual ~Thread() = default pode destruir o objeto enquanto
a thread subjacente ainda está em execução; altere o destrutor da classe Thread
para não liberar recursos sem tratamento: dentro de Thread::~Thread() verifique
se a thread está joinable (usar o método joinable() ou o campo que indica
estado) e em caso afirmativo chamar join() ou abortar/terminar explicitamente
(por exemplo std::terminate()) para evitar use-after-free da stack do kernel;
garanta também que Thread::join() exista e seja usado pelo código chamador
quando for apropriado.
- Around line 92-94: Substitua o uso de sizeof(stack_) ao chamar k_thread_create
pelo tamanho utilizável fornecido por K_THREAD_STACK_SIZEOF(stack_); ou seja, na
chamada k_thread_create(&thread_, stack_, sizeof(stack_), trampoline, this,
nullptr, nullptr, K_PRIO_PREEMPT(7), 0, K_NO_WAIT) troque sizeof(stack_) por
K_THREAD_STACK_SIZEOF(stack_) para que o argumento de tamanho da stack_ seja
correto ao usar K_THREAD_STACK_MEMBER/K_THREAD_STACK_DEFINE.
- Around line 29-31: Add an explicit `#include` <chrono> to
include/platform/thread.h and replace any raw int32_t casts around sleep_for
with chrono-safe conversions: use
std::chrono::duration_cast<std::chrono::milliseconds>(your_duration) (or
construct std::chrono::milliseconds directly) and pass that duration to
std::this_thread::sleep_for instead of casting to int32_t; if you must convert
to an integral count, clamp to the valid range (e.g. std::min/max with
INT32_MAX) before casting to avoid truncation.
- Around line 108-127: A move ctor/operator currently memcpy's k_thread and
stack while the kernel trampoline may still reference the original Thread (via
trampoline using this), which breaks kernel invariants; before copying
thread_/stack in Thread(Thread&&) and operator=(Thread&&) ensure the source is
not active: if o.joinable() call o.join() (or otherwise assert/return error) so
the thread has finished and the kernel no longer references its
stack/trampoline, then perform std::memcpy of thread_ and stack_ and transfer
entry_/joined_ (and null out o.entry_/set o.joined_). Also ensure you avoid
memcpy when the source is still joinable to prevent discarding a running entry
function.
In `@scripts/run_renode_test.sh`:
- Line 56: O comando atual que executa renode (a linha que usa renode
--disable-xwt -e "\$firmware=@$ELF_PATH; i @$RENODE_SCRIPT; start; sleep 10;
quit") não propaga o resultado do teste embarcado; altere a execução para
capturar a saída do Renode (stdout/stderr) e avaliar o status do teste (por
exemplo procurando tokens de sucesso/falha emitidos pelo firmware ou pelo script
de monitor), e então retornar esse status no script (ou seja, executar renode,
salvar sua saída em uma variável/arquivo, avaliar presença de "PASS"/"FAIL" ou o
token usado pelo test harness e usar exit <code> apropriado); referencie a
invocação que contém $ELF_PATH e $RENODE_SCRIPT e garanta que o script retorne
não-zero em caso de falha detectada em vez de confiar no sucesso do próprio
processo renode.
In `@scripts/run_zephyr_tests.sh`:
- Around line 51-55: The test runner currently swallows runtime failures for the
native_sim case by appending "|| true" to the timeout invocation, causing PASSED
to be incremented regardless; remove "|| true", capture the exit status of
"$build_dir/zephyr/zephyr.exe" (or the timeout command) and only increment
PASSED when the command exits with 0 (e.g., store the exit code from the timeout
call and check it before updating PASSED), keeping the printf and timeout usage
intact.
In `@src/platform/zephyr_memory.cpp`:
- Around line 26-32: ensure_slab_init can race because slab_initialized is
unsynchronized; make slab initialization thread-safe by using a synchronization
primitive (e.g., a mutex, spinlock, or atomic) to perform a double-checked init:
in allocate_message() or ensure_slab_init() first check slab_initialized, if
false acquire the lock, check slab_initialized again, then call
k_mem_slab_init(&message_slab, message_pool_buffer, sizeof(someip::Message),
CONFIG_SOMEIP_MESSAGE_POOL_SIZE) and set slab_initialized = true before
releasing the lock; reference symbols: ensure_slab_init, slab_initialized,
allocate_message, message_slab, message_pool_buffer, k_mem_slab_init,
CONFIG_SOMEIP_MESSAGE_POOL_SIZE.
- Around line 21-22: Replace the hardcoded __aligned(8) on the
message_pool_buffer declaration with a type-based alignment using
someip::Message's alignment (e.g., use alignas(alignof(someip::Message)) on the
static char message_pool_buffer[...] so storage is properly aligned for
placement-new of someip::Message); update the declaration that references
message_pool_buffer and ensure the alignment expression references
someip::Message to avoid magic constants.
In `@src/sd/sd_server.cpp`:
- Line 282: The member offer_timer_thread_ is being initialized by moving from a
temporary platform::Thread created inline (platform::Thread([this]() { ... })),
which risks a temporary-move/hazard; fix it by creating a named local
platform::Thread variable (e.g., platform::Thread t([this]() { ... });) and then
assign/move it into offer_timer_thread_ (offer_timer_thread_ = std::move(t);) or
construct offer_timer_thread_ in the initializer list instead—refer to the
symbol offer_timer_thread_ and platform::Thread to locate and apply this change.
In `@src/transport/tcp_transport.cpp`:
- Around line 207-212: Check and handle return values of
someip_set_blocking(listen_socket_fd_) and
someip_set_nonblocking(listen_socket_fd_) around the accept call: if
someip_set_blocking fails, log the error and skip the accept attempt (or retry)
instead of proceeding; after accept, if someip_set_nonblocking fails, log the
failure, attempt a fallback to restore non-blocking mode (e.g., via fcntl) and
if that also fails close listen_socket_fd_ (or break out of the accept loop) to
avoid leaving the loop in blocking mode; ensure any opened client_fd is closed
on error to avoid leaks.
In `@src/transport/udp_transport.cpp`:
- Around line 34-36: The constructor code in udp_transport.cpp that currently
conditionally throws "Invalid local endpoint" when exceptions are enabled can
leave objects invalid in no-exceptions builds; change the failure path so we
fail fast in all builds: either (A) replace the `#if` block with an unconditional
abort/terminate call (e.g., std::terminate() or std::abort()) so construction
never produces an invalid object when exceptions are disabled, or (B) convert
the constructor into a factory (e.g., static create(...) returning std::optional
or a Result) or set an explicit m_valid flag and prevent usage elsewhere; locate
the conditional throw (the "Invalid local endpoint" check inside the UDP
transport constructor/creation code) and implement one of these consistent
failure strategies so no-invalid-instance can be created.
In `@zephyr/boards/s32k388_renode/s32k388_renode.conf`:
- Around line 7-10: The board configuration is missing an explicit
CONFIG_NET_MAX_CONTEXTS override so SOME/IP Service Discovery (which opens both
multicast and unicast sockets) plus app sockets can exhaust the default socket
context pool; update the s32k388_renode config to set CONFIG_NET_MAX_CONTEXTS to
a higher value (e.g., 8 or 10) to accommodate SD's multicast and unicast sockets
and any application sockets, ensuring the change appears alongside the existing
network configs (referencing CONFIG_NETWORKING, CONFIG_NET_IPV4, CONFIG_NET_UDP,
CONFIG_NET_SOCKETS).
In `@zephyr/samples/hello_s32k/prj.conf`:
- Line 6: Update the CONFIG_MAIN_STACK_SIZE setting in prj.conf from 2048 to
8192 to match the other SOME/IP samples; modify the CONFIG_MAIN_STACK_SIZE entry
so the main thread stack size is increased to 8192 (so look for the
CONFIG_MAIN_STACK_SIZE key and change its value).
In `@zephyr/samples/net_test/prj.conf`:
- Around line 20-29: O prj.conf define valores de recurso agressivos que podem
quebrar boards com menos RAM; altere o prj.conf removendo ou reduzindo as chaves
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT, CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT,
CONFIG_NET_MAX_CONTEXTS, CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_BUF_TX_COUNT,
CONFIG_NET_PKT_RX_COUNT, CONFIG_NET_PKT_TX_COUNT, CONFIG_HEAP_MEM_POOL_SIZE e
CONFIG_MAIN_STACK_SIZE para valores conservadores/omita-os no prj.conf base, e
mova os valores específicos e maiores para overlays por placa (board overlays)
para cada target que precise desses limites maiores.
- Line 18: Remova a linha CONFIG_NET_SHELL=y do prj.conf base do sample para
evitar aumentar footprint em builds não-debug; em vez disso adicione essa
configuração apenas ao overlay de bring‑up/debug (por exemplo um arquivo de
overlay de debug usado no bring‑up) para que CONFIG_NET_SHELL seja ativado
somente em builds de depuração e não no prj.conf principal.
In `@zephyr/tests/test_transport/src/main.cpp`:
- Around line 52-53: The test continues after failures and performs only a
single receive attempt causing flakiness; make the test fail-fast and add a
bounded receive loop: after calling server.start() and the subsequent
server.send_message(), check their Result values and immediately abort/return
the test on non-success (replace or augment CHECK(result == Result::SUCCESS,
"server_start") and the send_message CHECKs with an early exit on failure), and
replace the single receive attempt at the later line (the lone
receive/receive_message call) with a bounded retry loop that waits up to a
configured timeout/attempt count (with short sleeps/backoff) before failing so
the receive path is deterministic.
- Line 47: Replace the hard-coded loopback addresses used when constructing
Endpoint objects: instead of Endpoint server_ep("127.0.0.1", 0) bind the server
to all interfaces (e.g. "0.0.0.0" or the library's IPv4-any constant) so tests
do not depend on loopback being enabled, and avoid using the literal "127.0.0.1"
for the client; have the client use the actual server address/port (e.g. obtain
the bound port from server_ep and construct client Endpoint from
server_ep.address()/port or resolve "localhost" via getaddrinfo) — update the
constructors referencing Endpoint, server_ep and any client_ep usage
accordingly.
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (31)
.github/workflows/zephyr.ymldocs/ZEPHYR_PORT_PROGRESS.mdinclude/core/session_manager.hinclude/e2e/e2e_crc.hinclude/e2e/e2e_header.hinclude/platform/memory.hinclude/platform/net.hinclude/platform/thread.hinclude/tp/tp_reassembler.hinclude/tp/tp_types.hinclude/transport/tcp_transport.hscripts/run_renode_test.shscripts/run_zephyr_tests.shscripts/zephyr_build.shsrc/platform/zephyr_memory.cppsrc/platform/zephyr_thread.cppsrc/sd/sd_client.cppsrc/sd/sd_message.cppsrc/sd/sd_server.cppsrc/transport/tcp_transport.cppsrc/transport/udp_transport.cppzephyr/CMakeLists.txtzephyr/boards/s32k388_renode/s32k388_renode.confzephyr/prj.confzephyr/samples/hello_s32k/prj.confzephyr/samples/net_test/prj.confzephyr/samples/someip_echo/prj.confzephyr/tests/test_core/prj.confzephyr/tests/test_core/src/main.cppzephyr/tests/test_transport/prj.confzephyr/tests/test_transport/src/main.cpp
| in_addr_t multicast_addr = inet_addr(config_.multicast_address.c_str()); | ||
| multicast_option->set_ipv4_address(multicast_addr); | ||
| multicast_option->set_port(htons(config_.multicast_port)); | ||
| multicast_option->set_port(someip_htons(config_.multicast_port)); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cd src/sd && wc -l sd_server.cppRepository: vtz/opensomeip
Length of output: 75
🏁 Script executed:
cd src/sd && sed -n '195,210p' sd_server.cppRepository: vtz/opensomeip
Length of output: 910
🏁 Script executed:
cd src/sd && sed -n '350,365p' sd_server.cppRepository: vtz/opensomeip
Length of output: 883
🏁 Script executed:
cd src/sd && sed -n '520,535p' sd_server.cppRepository: vtz/opensomeip
Length of output: 883
🏁 Script executed:
fd -t f '\.(h|hpp)$' | xargs rg -n 'set_port\s*\(' -A 2 -B 1 | head -100Repository: vtz/opensomeip
Length of output: 855
🏁 Script executed:
rg -t cpp -t hpp 'void\s+set_port\s*\(' -A 5Repository: vtz/opensomeip
Length of output: 85
🏁 Script executed:
rg -n 'IPv4MulticastOption|IPv4EndpointOption' --type-add 'header:h,hpp' -t header -A 20 | head -150Repository: vtz/opensomeip
Length of output: 206
🏁 Script executed:
rg -n 'serialize\s*\(' src/sd/sd_message.cpp -A 15 | head -200Repository: vtz/opensomeip
Length of output: 6681
🏁 Script executed:
fd -t f 'sd_message\.(h|cpp)' -x grep -n 'class IPv4' {} +Repository: vtz/opensomeip
Length of output: 295
🏁 Script executed:
cd src/sd && grep -n 'class IPv4MulticastOption\|class IPv4EndpointOption' sd_message.hRepository: vtz/opensomeip
Length of output: 103
🏁 Script executed:
cd src/sd && sed -n '130,200p' sd_message.hRepository: vtz/opensomeip
Length of output: 113
🏁 Script executed:
cd src/sd && sed -n '160,250p' sd_message.hRepository: vtz/opensomeip
Length of output: 113
🏁 Script executed:
cd src/sd && grep -n 'IPv4MulticastOption::serialize\|IPv4EndpointOption::serialize' sd_message.cppRepository: vtz/opensomeip
Length of output: 188
🏁 Script executed:
cd src/sd && rg -n 'serialize' sd_message.cpp -B 3 -A 10 | head -250Repository: vtz/opensomeip
Length of output: 7502
Remove someip_htons() call to prevent double byte-order swap.
Line 202 uses someip_htons(config_.multicast_port) before passing to set_port(), while lines 357 and 527 pass host-order values directly. The serialize() method performs bit-shifting that assumes host-order input, so pre-swapping on line 202 causes the port to be serialized with swapped bytes, advertising the wrong port.
🛠 Suggested fix
- multicast_option->set_port(someip_htons(config_.multicast_port));
+ multicast_option->set_port(config_.multicast_port);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| multicast_option->set_port(someip_htons(config_.multicast_port)); | |
| multicast_option->set_port(config_.multicast_port); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/sd/sd_server.cpp` at line 202, The multicast port is being
pre-byte-swapped before serialization which causes double swapping; update the
call at multicast_option->set_port to pass the host-order value directly (use
config_.multicast_port without wrapping in someip_htons) so that the existing
serialize() logic performs the correct byte-order conversion; locate the
multicast_option->set_port invocation in sd_server.cpp and remove the
someip_htons() wrapper, keeping the rest of the serialize() path unchanged.
| message = std::make_shared<Message>(); | ||
| if (message && message->deserialize(message_data)) { |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Use the platform message allocator in this hot path.
Line 579 uses std::make_shared<Message>(), which bypasses the new Zephyr-aware allocator abstraction.
♻️ Suggested refactor
`#include` "platform/net.h"
+#include "platform/memory.h"
@@
- message = std::make_shared<Message>();
+ message = platform::allocate_message();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/transport/tcp_transport.cpp` around lines 579 - 580, Replace the direct
std::make_shared<Message>() allocation with the platform/Zephyr-aware message
allocator so the hot path uses the platform allocator; locate the allocation of
message (currently message = std::make_shared<Message>()) and call the platform
allocator factory (e.g., platform::allocMessage() or the project’s
MessageFactory/PlatformMessageAllocator) to obtain the shared/owned Message
instance, preserve the existing null check and the call to
message->deserialize(message_data), and ensure the returned object type and
ownership semantics match the rest of the code.
| if(NOT CONFIG_ARCH_POSIX) | ||
| # Embedded targets only (S32K344, S32K388, etc.) | ||
| zephyr_library_sources_ifdef(CONFIG_SOMEIP | ||
| ${SOMEIP_SRC}/platform/zephyr_thread.cpp | ||
| ${SOMEIP_SRC}/platform/zephyr_memory.cpp | ||
| ) | ||
| endif() |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Redundant CONFIG_SOMEIP guard inside the outer if(CONFIG_SOMEIP) block.
zephyr_library_sources_ifdef(CONFIG_SOMEIP ...) at Line 91 re-checks a condition that is already guaranteed true by the outer if(CONFIG_SOMEIP) at Line 10. Use plain zephyr_library_sources() here.
♻️ Proposed fix
if(NOT CONFIG_ARCH_POSIX)
# Embedded targets only (S32K344, S32K388, etc.)
- zephyr_library_sources_ifdef(CONFIG_SOMEIP
+ zephyr_library_sources(
${SOMEIP_SRC}/platform/zephyr_thread.cpp
${SOMEIP_SRC}/platform/zephyr_memory.cpp
)
endif()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/CMakeLists.txt` around lines 89 - 95, The block redundantly re-checks
CONFIG_SOMEIP using zephyr_library_sources_ifdef inside an outer
if(CONFIG_SOMEIP) guard; replace the inner
zephyr_library_sources_ifdef(CONFIG_SOMEIP ...) call with
zephyr_library_sources(...) so the sources
${SOMEIP_SRC}/platform/zephyr_thread.cpp and
${SOMEIP_SRC}/platform/zephyr_memory.cpp are added unconditionally within the
already-true CONFIG_SOMEIP branch (modify the invocation of
zephyr_library_sources_ifdef to zephyr_library_sources in that block).
| CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" | ||
| CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Check file existence and content ==="
if [ -f "zephyr/samples/someip_echo/prj.conf" ]; then
echo "File exists. Content (lines 10-20):"
sed -n '10,20p' "zephyr/samples/someip_echo/prj.conf"
else
echo "File not found at zephyr/samples/someip_echo/prj.conf"
echo "Searching for prj.conf files with 'someip_echo':"
find . -name "prj.conf" -type f | grep -i someip || echo "No matches found"
fi
echo
echo "=== Check where endpoint addresses are currently defined ==="
rg -n 'CONFIG_NET_CONFIG_(MY|PEER)_IPV4_ADDR' -g '**/*.conf' | head -20
echo
echo "=== Check whether docs explain endpoint override usage ==="
rg -n 'someip_echo|EXTRA_CONF_FILE|NET_CONFIG_(MY|PEER)_IPV4_ADDR|192\.0\.2\.' -g 'README*' -g '**/*.md' | head -30Repository: vtz/opensomeip
Length of output: 1372
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Check for overlay files in samples ==="
find zephyr/samples -name "*.overlay" -o -name "*.conf" | grep -E "(overlay|conf)" | head -20
echo
echo "=== Check if there's a west.yml or build configuration ==="
if [ -f "west.yml" ]; then
head -30 west.yml
fi
echo
echo "=== Check someip_echo sample directory structure ==="
ls -la zephyr/samples/someip_echo/ 2>/dev/null || echo "Directory listing failed"
echo
echo "=== Check for build documentation or CMAKE files ==="
find zephyr/samples/someip_echo -name "CMakeLists.txt" -o -name "*.md" -o -name "*.rst" 2>/dev/null | xargs ls -la 2>/dev/null || echo "No build files found"
echo
echo "=== Check if boards directory has overlay pattern ==="
ls -la zephyr/boards/ | head -20
</parameter>Repository: vtz/opensomeip
Length of output: 1302
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== CMakeLists.txt content ==="
cat zephyr/samples/someip_echo/CMakeLists.txt
echo
echo "=== Check for README in someip_echo ==="
find zephyr/samples/someip_echo -iname "README*" -o -iname "*.md" 2>/dev/null | xargs cat 2>/dev/null || echo "No README found"
echo
echo "=== Search for EXTRA_CONF_FILE or overlay usage in project ==="
rg -i 'EXTRA_CONF_FILE|overlay|prj\.conf.*override' --max-count 10
echo
echo "=== Check if other Zephyr samples in native_sim have similar pattern ==="
grep -r "CONFIG_NET_CONFIG_MY_IPV4_ADDR" zephyr/samples/ 2>/dev/null | cut -d: -f1 | sort | uniq
echo
echo "=== Check native_sim.conf - is it used as board overlay? ==="
head -20 zephyr/boards/native_sim.conf
</parameter>Repository: vtz/opensomeip
Length of output: 452
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Check all prj.conf files to understand pattern ==="
for file in $(find zephyr -name "prj.conf" -type f); do
echo "=== $file ==="
head -5 "$file"
echo
done | head -100
echo
echo "=== Check if native_sim.conf is board-specific extension ==="
cat zephyr/boards/native_sim.conf
echo
echo "=== Search for Zephyr documentation about configuration ==="
find . -name "*.md" -o -name "*.rst" | xargs grep -l "prj.conf\|CONFIG_NET" 2>/dev/null | head -5
</parameter>Repository: vtz/opensomeip
Length of output: 1938
Consider externalizing network configuration for broader reusability.
Hard-coding endpoint addresses in prj.conf limits reusability across different deployment environments. If expanding this sample beyond native_sim, consider using board-specific overlays or environment-based configuration to allow runtime/CI customization without modifying the base sample config.
Note: This is a structural improvement but not urgent—the current approach works for the existing native_sim target and matches patterns used elsewhere in the project.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/someip_echo/prj.conf` around lines 14 - 15, The prj.conf
currently hard-codes network addresses via CONFIG_NET_CONFIG_MY_IPV4_ADDR and
CONFIG_NET_CONFIG_PEER_IPV4_ADDR which reduces reusability; refactor by removing
these fixed values from prj.conf and instead load them via board- or
environment-specific overlays (e.g., board overlay Kconfig fragments or
devicetree/overlay files) or via CI/runtime-provided build variables so
different targets can supply addresses without editing the sample; update
documentation/comments near prj.conf to explain how to override these configs at
build/runtime.
| CONFIG_HEAP_MEM_POOL_SIZE=131072 | ||
| CONFIG_MAIN_STACK_SIZE=8192 |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== 1. Inspect the actual prj.conf file ==="
if [ -f "zephyr/samples/someip_echo/prj.conf" ]; then
echo "File found. Contents:"
cat -n "zephyr/samples/someip_echo/prj.conf"
else
echo "File not found. Searching for it:"
find . -name "prj.conf" -path "*/someip_echo*" 2>/dev/null || echo "Not found"
fi
echo
echo "=== 2. Check for board overlay files in the sample ==="
if [ -d "zephyr/samples/someip_echo" ]; then
echo "Sample directory contents:"
ls -la "zephyr/samples/someip_echo/" | head -30
echo
echo "Any .conf files in this directory:"
find "zephyr/samples/someip_echo" -name "*.conf" -type f
else
echo "Sample directory not found at that location"
fi
echo
echo "=== 3. Check Zephyr default stack/heap sizes ==="
rg 'CONFIG_HEAP_MEM_POOL_SIZE|CONFIG_MAIN_STACK_SIZE' zephyr/ -t conf --max-count=20 | head -40
echo
echo "=== 4. Compare with other sample configs ==="
echo "Sampling 5 other samples with CONFIG_HEAP_MEM_POOL_SIZE:"
rg -l 'CONFIG_HEAP_MEM_POOL_SIZE=' zephyr/samples/ -t conf 2>/dev/null | head -5 | while read f; do
echo "File: $f"
rg -A 1 -B 1 'CONFIG_HEAP_MEM_POOL_SIZE=' "$f"
echo
doneRepository: vtz/opensomeip
Length of output: 1391
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== 1. Check Zephyr default stack/heap sizes in this repo ==="
rg 'CONFIG_HEAP_MEM_POOL_SIZE|CONFIG_MAIN_STACK_SIZE' zephyr/ --max-count=30
echo
echo "=== 2. Compare memory config across multiple samples ==="
echo "Samples with CONFIG_HEAP_MEM_POOL_SIZE set:"
find zephyr/samples -name "prj.conf" -type f -exec grep -l 'CONFIG_HEAP_MEM_POOL_SIZE' {} \; | head -10
echo
echo "Sample values:"
find zephyr/samples -name "prj.conf" -type f -exec grep 'CONFIG_HEAP_MEM_POOL_SIZE=' {} + | head -15
echo
echo "=== 3. Check if other networking/SOMEIP samples exist ==="
find zephyr/samples -type d -name "*someip*" -o -name "*net*" | head -10
echo
echo "=== 4. Look for board-specific overlay patterns ==="
find zephyr/samples -name "*.conf" -path "*boards*" | head -10Repository: vtz/opensomeip
Length of output: 2497
These memory values are consistent across all SOMEIP samples and appear necessary for functionality.
The values CONFIG_HEAP_MEM_POOL_SIZE=131072 and CONFIG_MAIN_STACK_SIZE=8192 are used identically in all SOMEIP samples (client, server, echo, sd_client) and the root project config, indicating they're required for SOMEIP protocol support rather than "aggressive" defaults. Moving to board-specific overlays is a valid refactoring pattern if multi-board targeting becomes a future goal, but the current values are consistent with the codebase's baseline requirements.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/someip_echo/prj.conf` around lines 17 - 18, The project-wide
prj.conf must retain the SOMEIP-required memory settings rather than removing or
relocating them; ensure CONFIG_HEAP_MEM_POOL_SIZE=131072 and
CONFIG_MAIN_STACK_SIZE=8192 remain in prj.conf (used by SOMEIP samples like
someip_echo, someip_client, someip_server, sd_client) or, if you refactor to
board overlays, duplicate those exact settings into every board-specific overlay
so all SOMEIP samples continue to receive the same baseline values.
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (8)
src/transport/endpoint.cpp (1)
71-73:⚠️ Potential issue | 🟡 Minor
port_ > 65535is a tautological comparison — dead code.
port_isuint16_t, whose maximum value is exactly 65535, so this condition is always false and will trigger-Wtype-limitswarnings on GCC/Clang.🛠️ Proposed fix
- // Check port range (allow 0 for auto-assignment) - if (port_ > 65535) { - return false; - } - // Check address format return is_valid_ipv4(address_) || is_valid_ipv6(address_);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/endpoint.cpp` around lines 71 - 73, The check "if (port_ > 65535)" is tautological because port_ is uint16_t; remove this dead branch in src/transport/endpoint.cpp (the check around the port_ member). If you intended to accept/validate values >65535, either change the port_ storage type (e.g., to uint32_t) or validate the original input before casting/assigning to port_ (e.g., in the constructor or setPort method) so you don't rely on an impossible comparison against port_ itself.src/rpc/rpc_client.cpp (1)
174-190: 🛠️ Refactor suggestion | 🟠 MajorCallbacks are invoked while holding
pending_calls_mutex_— latent deadlock risk.Both
cancel_call(line 185) andon_message_received(line 233) invoke the user-provided callback while holdingpending_calls_mutex_. If a callback ever calls back intoRpcClientmethods (e.g.,cancel_call,call_method_async), it will deadlock.A safer pattern is to extract the callback and erase the entry under the lock, then invoke the callback after releasing the lock:
Suggested refactor for cancel_call
bool cancel_call(RpcCallHandle handle) { + RpcCallback cb; + uint16_t svc_id, sess_id; + MethodId meth_id; - platform::ScopedLock lock(pending_calls_mutex_); - auto it = pending_calls_.find(handle); - if (it == pending_calls_.end()) { - return false; - } - - // Call callback with cancellation result - if (it->second.callback) { - RpcResponse response(it->second.service_id, it->second.method_id, - client_id_, it->second.session_id, RpcResult::INTERNAL_ERROR); - it->second.callback(response); + { + platform::ScopedLock lock(pending_calls_mutex_); + auto it = pending_calls_.find(handle); + if (it == pending_calls_.end()) { + return false; + } + cb = std::move(it->second.callback); + svc_id = it->second.service_id; + meth_id = it->second.method_id; + sess_id = it->second.session_id; + pending_calls_.erase(it); } - pending_calls_.erase(it); + if (cb) { + RpcResponse response(svc_id, meth_id, client_id_, sess_id, RpcResult::INTERNAL_ERROR); + cb(response); + } return true; }Also applies to: 211-241
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/rpc/rpc_client.cpp` around lines 174 - 190, cancel_call and on_message_received currently invoke user callbacks while holding pending_calls_mutex_, risking deadlock if callbacks call back into RpcClient; fix by extracting the callback (and any data needed to build RpcResponse) and erasing the pending_calls_ entry while holding pending_calls_mutex_, then release the lock and invoke the callback outside the lock. Specifically, in cancel_call and in on_message_received: grab it->second.callback (and session/service/method ids or build RpcResponse data) into local variables, erase the map entry under pending_calls_mutex_, drop the lock, then call the saved callback; ensure you still construct RpcResponse using the saved data before invoking the callback.src/sd/sd_client.cpp (2)
373-394: 🛠️ Refactor suggestion | 🟠 Major
subscriptions_mutex_lock scope is broader than necessary.Line 374 acquires
subscriptions_mutex_outside of any block scope, so it remains held through thepending_finds_mutex_acquisition at line 382. While this doesn't cause a deadlock with the current code, nested lock acquisition is fragile and the subscription lookup only needs lines 375-378.Suggested refactor
// Notify subscribers - platform::ScopedLock lock(subscriptions_mutex_); - auto sub_it = service_subscriptions_.find(instance.service_id); - if (sub_it != service_subscriptions_.end() && sub_it->second.available_callback) { - sub_it->second.available_callback(instance); + { + platform::ScopedLock lock(subscriptions_mutex_); + auto sub_it = service_subscriptions_.find(instance.service_id); + if (sub_it != service_subscriptions_.end() && sub_it->second.available_callback) { + sub_it->second.available_callback(instance); + } } // Check for pending finds🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/sd/sd_client.cpp` around lines 373 - 394, subscriptions_mutex_ is held too long around the pending_finds_ work; narrow its scope so we don't hold subscriptions_mutex_ while acquiring pending_finds_mutex_. Specifically, in the block that references service_subscriptions_ (use service_subscriptions_.find(instance.service_id) and sub_it->second.available_callback), acquire platform::ScopedLock lock(subscriptions_mutex_) only for the lookup/callback retrieval, copy the available_callback (and any needed data like instance or a small flag) out while holding the lock, then release it before entering the block that acquires platform::ScopedLock lock(pending_finds_mutex_) to iterate pending_finds_ and call their callbacks; ensure you copy any callback objects (available_callback and pending find callbacks) out of their containers before invoking them to avoid use-after-release races.
270-284:⚠️ Potential issue | 🔴 CriticalReplace
std::dynamic_pointer_castwithstd::static_pointer_castat lines 271 and 281 for Zephyr compatibility.Lines 271 and 281 still use
std::dynamic_pointer_cast, which requires RTTI. Since Zephyr uses-fno-rttiby default, these calls will fail to compile. The docs confirm this migration was intended in Phase 3. Becausetransport_is always constructed asUdpTransport(line 43),static_pointer_castis safe and correct.Proposed fix
bool join_multicast_group() { - auto udp_transport = std::dynamic_pointer_cast<transport::UdpTransport>(transport_); + auto udp_transport = std::static_pointer_cast<transport::UdpTransport>(transport_); if (!udp_transport) { return false; } void leave_multicast_group() { - auto udp_transport = std::dynamic_pointer_cast<transport::UdpTransport>(transport_); + auto udp_transport = std::static_pointer_cast<transport::UdpTransport>(transport_); if (udp_transport) {After conversion, the null checks become dead code since the cast always succeeds; consider removing them or keeping as defensive guards.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/sd/sd_client.cpp` around lines 270 - 284, Replace the RTTI-dependent std::dynamic_pointer_cast calls with std::static_pointer_cast for Zephyr compatibility: in join_multicast_group() and leave_multicast_group() cast transport_ to std::static_pointer_cast<transport::UdpTransport>(transport_) (refer to join_multicast_group, leave_multicast_group, transport_, and transport::UdpTransport) and keep or remove the subsequent null checks as desired since transport_ is always constructed as UdpTransport; ensure the return/conditional logic still calls join_multicast_group("224.224.224.245") and leave_multicast_group("224.224.224.245") on the resulting pointer.src/sd/sd_server.cpp (1)
92-98:⚠️ Potential issue | 🟠 MajorNarrow lock scope in
shutdown()to avoid stop-path deadlock risk.At Line 92,
offered_services_mutex_remains held throughleave_multicast_group()andtransport_->stop(). If the transport stop path waits on callbacks that need the same mutex, shutdown can deadlock.Proposed fix
- platform::ScopedLock lock(offered_services_mutex_); - offered_services_.clear(); + { + platform::ScopedLock lock(offered_services_mutex_); + offered_services_.clear(); + } // Leave multicast group leave_multicast_group(); transport_->stop();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/sd/sd_server.cpp` around lines 92 - 98, In shutdown(), the offered_services_mutex_ is held while calling leave_multicast_group() and transport_->stop(), risking deadlock if those stop paths invoke callbacks that need the same mutex; fix by narrowing the lock scope: acquire platform::ScopedLock around offered_services_.clear() only (or use a short scope/block), then release the mutex before calling leave_multicast_group() and transport_->stop() so those functions run without holding offered_services_mutex_.src/events/event_subscriber.cpp (2)
97-122:⚠️ Potential issue | 🟠 MajorDo not hold
subscriptions_mutex_acrosstransport_->send_message().Network I/O under this mutex can stall subscription operations and deadlock if transport callbacks re-enter subscription paths.
🔧 Suggested lock scoping
- platform::ScopedLock subs_lock(subscriptions_mutex_); - std::string key = make_subscription_key(service_id, instance_id, eventgroup_id); - subscriptions_[key] = sub_info; + std::string key = make_subscription_key(service_id, instance_id, eventgroup_id); + { + platform::ScopedLock subs_lock(subscriptions_mutex_); + subscriptions_[key] = sub_info; + } ... - Result send_result = transport_->send_message(subscription_msg, service_endpoint); + Result send_result = transport_->send_message(subscription_msg, service_endpoint); bool success = (send_result == Result::SUCCESS); if (!success) { - subscriptions_.erase(key); + platform::ScopedLock subs_lock(subscriptions_mutex_); + subscriptions_.erase(key); }Also applies to: 130-158
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/events/event_subscriber.cpp` around lines 97 - 122, The code currently holds platform::ScopedLock subscriptions_mutex_ while calling transport_->send_message, which risks blocking and deadlocks; change the lock scope in the subscribe flow (the block using platform::ScopedLock subs_lock, make_subscription_key, and subscriptions_ assignment) so you only hold the mutex for creating the key and inserting subscriptions_[key] = sub_info, then release the lock before calling transport_->send_message(service_endpoint); if send_message fails, re-acquire subscriptions_mutex_ and erase subscriptions_. Apply the same change to the analogous section referenced at lines 130-158 to avoid holding subscriptions_mutex_ across network I/O.
261-279:⚠️ Potential issue | 🟠 MajorInvoke subscriber callbacks outside
subscriptions_mutex_.
sub_info.notification_callback(...)under lock can deadlock if callback code re-enters subscriber APIs that also locksubscriptions_mutex_.🔧 Suggested callback dispatch pattern
- platform::ScopedLock subs_lock(subscriptions_mutex_); + EventNotificationCallback callback_to_invoke; + EventNotification notification(service_id, 0, event_id); + { + platform::ScopedLock subs_lock(subscriptions_mutex_); uint16_t service_id = message->get_service_id(); uint16_t event_id = message->get_method_id(); ... - if (sub_info.notification_callback) { - sub_info.notification_callback(notification); - } + callback_to_invoke = sub_info.notification_callback; ... break; } } + } + + if (callback_to_invoke) { + callback_to_invoke(notification); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/events/event_subscriber.cpp` around lines 261 - 279, Currently the code calls sub_info.notification_callback(notification) while holding subscriptions_mutex_, which risks deadlock if callbacks re-enter subscriber APIs; modify OnReceive (or the function containing this loop) to collect the EventNotification objects and corresponding callbacks (e.g., pairs of EventNotification and sub_info.notification_callback) into a local vector while holding subscriptions_mutex_ and then release subscriptions_mutex_ and invoke each callback from that vector; use the existing symbols subscriptions_mutex_, subscriptions_, sub_info.notification_callback, and EventNotification to locate and implement the change.src/transport/udp_transport.cpp (1)
341-348: 🛠️ Refactor suggestion | 🟠 MajorUse
platform::allocate_message()instead ofstd::make_shared<Message>()in the receive path.Line 343 bypasses the Zephyr slab allocator introduced in this PR. On embedded targets, this allocates from the heap instead of the pre-allocated pool, defeating the purpose of the memory abstraction.
♻️ Proposed fix
Add the include at the top of the file:
`#include` "platform/memory.h"Then apply:
- MessagePtr message = std::make_shared<Message>(); + MessagePtr message = platform::allocate_message(); + if (!message) { + continue; // Pool exhausted + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/udp_transport.cpp` around lines 341 - 348, Replace the heap allocation of a Message in the receive path with the Zephyr slab allocator: include "platform/memory.h" at the top of the file and use platform::allocate_message() instead of std::make_shared<Message>() when constructing MessagePtr (the variable named message) before deserializing; keep the existing deserialize, platform::ScopedLock on queue_mutex_, and receive_queue_.push(message) logic unchanged so messages come from the pre-allocated pool.
♻️ Duplicate comments (20)
zephyr/tests/test_core/prj.conf (1)
1-3:CONFIG_REQUIRES_FULL_LIBCPP=ycorrectly added.The previously identified missing entry is now present, ensuring STL availability (
std::vectoretc.) for the test build.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_core/prj.conf` around lines 1 - 3, The test config now correctly includes CONFIG_REQUIRES_FULL_LIBCPP=y alongside CONFIG_STD_CPP17=y and CONFIG_CPP=y, so no code changes are required; confirm the presence of the CONFIG_REQUIRES_FULL_LIBCPP flag in the prj.conf (look for the CONFIG_REQUIRES_FULL_LIBCPP, CONFIG_STD_CPP17, and CONFIG_CPP entries) and approve/merge the change.zephyr/samples/net_test/prj.conf (2)
17-18:⚠️ Potential issue | 🟡 MinorGate
CONFIG_NET_SHELLto debug-only overlays.Line 18 enables shell support unconditionally in the base sample config. Keep
CONFIG_NET_LOG_LEVEL_INFin base and moveCONFIG_NET_SHELLto a debug/bring-up overlay.Proposed change
CONFIG_NET_LOG_LEVEL_INF=y -CONFIG_NET_SHELL=y +# Keep NET_SHELL in debug overlay only.#!/bin/bash # Verify where NET_SHELL is currently defined for the sample. rg -n '^\s*CONFIG_NET_SHELL' zephyr/samples/net_test fd -a '.*(overlay|debug).*\.conf' zephyr/samples/net_test🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/net_test/prj.conf` around lines 17 - 18, The base sample currently enables CONFIG_NET_SHELL unconditionally; leave CONFIG_NET_LOG_LEVEL_INF in the base prj.conf but remove CONFIG_NET_SHELL from the base and add it to a debug/bring-up overlay so shell support is only enabled for debug builds (e.g., create a debug overlay file and set CONFIG_NET_SHELL=y there). Update/remove the CONFIG_NET_SHELL line in the base prj.conf and add the same symbol to your debug/bring-up overlay file used during development; ensure the overlay filename matches your project's debug overlay convention so the shell is only built for debug/bring-up configurations.
20-29:⚠️ Potential issue | 🟠 MajorMove aggressive resource sizing out of shared
prj.conf.Line 20-Line 29 hard-code high network/memory limits in the common sample config, which hurts board portability and can fail on tighter RAM targets. Put these into board-specific overlays.
Proposed change
-CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 -CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=2 -CONFIG_NET_MAX_CONTEXTS=10 -CONFIG_NET_BUF_RX_COUNT=16 -CONFIG_NET_BUF_TX_COUNT=16 -CONFIG_NET_PKT_RX_COUNT=8 -CONFIG_NET_PKT_TX_COUNT=8 - -CONFIG_HEAP_MEM_POOL_SIZE=131072 -CONFIG_MAIN_STACK_SIZE=4096 +# Move board/resource-specific sizing to overlays (e.g., native_sim or debug overlays).#!/bin/bash # Verify whether these knobs are still pinned in shared sample config. rg -n 'CONFIG_(NET_IF_UNICAST_IPV4_ADDR_COUNT|NET_IF_MCAST_IPV4_ADDR_COUNT|NET_MAX_CONTEXTS|NET_BUF_RX_COUNT|NET_BUF_TX_COUNT|NET_PKT_RX_COUNT|NET_PKT_TX_COUNT|HEAP_MEM_POOL_SIZE|MAIN_STACK_SIZE)' zephyr/samples/net_test🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/net_test/prj.conf` around lines 20 - 29, The shared sample prj.conf contains aggressive, board-specific knobs (CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT, CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT, CONFIG_NET_MAX_CONTEXTS, CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_BUF_TX_COUNT, CONFIG_NET_PKT_RX_COUNT, CONFIG_NET_PKT_TX_COUNT, CONFIG_HEAP_MEM_POOL_SIZE, CONFIG_MAIN_STACK_SIZE); remove these entries from zephyr/samples/net_test/prj.conf and relocate them into the appropriate board-specific overlay or per-board prj.conf so only targets that need the higher network/memory limits opt in; ensure any boards left without these overrides still build with safe defaults and document the new per-board override names so maintainers know where to tune them.src/transport/endpoint.cpp (1)
15-19:<cctype>addition resolves the previous review finding.Past concern addressed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/endpoint.cpp` around lines 15 - 19, The previous missing header for character classification has been fixed by adding <cctype> to the include list; confirm that functions like isspace/isdigit (or other ctype functions used by code in src/transport/endpoint.cpp) now compile and keep the new `#include` <cctype> in place, removing no other includes or changes.docs/ZEPHYR_PORT_PROGRESS.md (2)
6-6: "Targets" should use a Portuguese term for consistency.The document is written in Portuguese; this English term was flagged in a prior review.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/ZEPHYR_PORT_PROGRESS.md` at line 6, The header term "**Targets**" in docs/ZEPHYR_PORT_PROGRESS.md is in English; change it to a Portuguese equivalent (e.g., "**Alvos**" or "**Plataformas**") so the document remains consistent in Portuguese, updating the line that currently reads "**Targets**: native_sim, mr_canhubk3 (S32K344), s32k388_renode (S32K388)" to use the chosen Portuguese term.
26-28:CONFIG_REQUIRES_FULL_LIBCPPdoes not replaceCONFIG_NEWLIB_LIBC.This misleading note was flagged in a prior review and remains unaddressed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/ZEPHYR_PORT_PROGRESS.md` around lines 26 - 28, The note claiming CONFIG_REQUIRES_FULL_LIBCPP replaces CONFIG_NEWLIB_LIBC is incorrect; update the text in ZEPHYR_PORT_PROGRESS.md to remove or reword that sentence and explicitly state the correct relationship: CONFIG_REQUIRES_FULL_LIBCPP enables the full C++ library, whereas CONFIG_NEWLIB_LIBC (and the NEWLIB_LIBC/EXTERNAL_LIBC Kconfig symbols) control which C library is used on native_sim; mention that NEWLIB_LIBC conflicts with EXTERNAL_LIBC on native_sim and that CONFIG_REQUIRES_FULL_LIBCPP does not substitute for CONFIG_NEWLIB_LIBC..github/workflows/zephyr.yml (3)
35-39: Consider extracting the duplicated Zephyr init into a composite action.This was flagged in a prior review.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 35 - 39, The "Init Zephyr" step is duplicated; extract it into a reusable composite GitHub Action (e.g., create a composite action named init-zephyr with the steps pip install jsonschema, west init /tmp/zp && cd /tmp/zp, and west update --narrow -o=--depth=1 && west zephyr-export) and then replace the inline step (the step with name "Init Zephyr") with a single uses: ./path-to-init-zephyr or uses: org/repo/.github/actions/init-zephyr@ref, ensuring inputs/outputs and permissions match the original behavior.
30-34: SDK downloads lack checksum verification.This supply-chain risk was flagged in a prior review and remains unaddressed.
Also applies to: 67-73
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 30 - 34, The "Install Zephyr SDK" step is downloading and extracting the SDK without verifying integrity; update that GitHub Actions step (and the similar step at lines 67-73) to download the official checksum (or .sha256/.sha256sum) for zephyr-sdk-0.17.0, verify the archive with sha256sum (or gpg/secure signing if available) and only extract if the checksum matches, failing the job on mismatch; reference the "Install Zephyr SDK" job/step name to locate where to add the checksum download and verification logic.
19-19:⚠️ Potential issue | 🟡 MinorUnquoted
$(nproc)— shellcheck SC2046.actionlint flags this as a word-splitting risk.
Suggested fix
- cmake --build build -j$(nproc) + cmake --build build -j"$(nproc)"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml at line 19, The workflow line containing the cmake invocation (the token "cmake --build build -j$(nproc)") risks word-splitting; update that command to quote the command substitution (e.g., use -j"$(nproc)") so the "-j" argument receives a single value and avoids shellcheck SC2046/actionlint warnings; locate the invocation of cmake in the zephyr.yml workflow and replace the unquoted $(nproc) usage with a quoted form.scripts/run_renode_test.sh (1)
55-56: Renodequitalways exits 0 — test failures are not propagated.The
sleep 10; quitapproach neither detects test pass/fail nor adapts to test duration. This was flagged in a prior review and remains unaddressed.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/run_renode_test.sh` around lines 55 - 56, The current renode invocation uses a fixed "start; sleep 10; quit" which always exits 0 and doesn't propagate test failures; change this so the test runner reports and propagates an actual exit code: update the renode command that uses RENODE_SCRIPT and ELF_PATH (the line with renode --disable-xwt -e "... start; sleep 10; quit") to either (a) have the RENODE_SCRIPT write the test result/exit code to a sentinel file and have the shell wait for that file and then exit with that code, or (b) have the script call renode's exit <code> inside the -e script instead of quit and let the shell capture renode's non-zero exit status—remove the fixed sleep and ensure the final shell exit uses the propagated test exit code.src/sd/sd_server.cpp (1)
202-202:⚠️ Potential issue | 🟠 MajorRemove pre-swap before
set_port()to avoid wrong advertised multicast port.At Line 202,
someip_htons(config_.multicast_port)likely causes a double byte-order conversion during option serialization.Proposed fix
- multicast_option->set_port(someip_htons(config_.multicast_port)); + multicast_option->set_port(config_.multicast_port);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/sd/sd_server.cpp` at line 202, The multicast port is being pre-byte-swapped before serialization; remove the call to someip_htons and pass the raw config_.multicast_port into multicast_option->set_port so the option serialization does the correct byte-ordering (i.e., replace multicast_option->set_port(someip_htons(config_.multicast_port)) with passing config_.multicast_port directly).zephyr/samples/hello_s32k/prj.conf (1)
6-6: 🧹 Nitpick | 🔵 TrivialRe-check
CONFIG_MAIN_STACK_SIZE=2048for C++ runtime headroom.At Line 6, this is materially lower than other Zephyr SOME/IP samples and may be fragile with full libc++ startup paths.
#!/bin/bash # Compare main stack sizes across Zephyr sample/project configs fd -t f 'prj.conf' zephyr | xargs rg -n '^CONFIG_MAIN_STACK_SIZE='Expected: confirm whether
hello_s32kis the outlier and decide if it should be aligned (e.g., 4096/8192).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/samples/hello_s32k/prj.conf` at line 6, The pr sets CONFIG_MAIN_STACK_SIZE=2048 in the hello_s32k sample which appears lower than other Zephyr SOME/IP C++ samples and may be insufficient for libc++ startup; verify that hello_s32k is an outlier by comparing CONFIG_MAIN_STACK_SIZE across samples (as suggested) and, if confirmed, increase CONFIG_MAIN_STACK_SIZE in the hello_s32k prj.conf to match the common value used by other samples (e.g., 4096 or 8192) so the C++ runtime has adequate headroom; update the prj.conf entry CONFIG_MAIN_STACK_SIZE accordingly and rerun the sample build/tests to confirm no stack-related failures.zephyr/tests/test_transport/src/main.cpp (1)
71-80:⚠️ Potential issue | 🟡 MinorShort-circuit after failed
send_message()to avoid cascading failures.At Lines 71-80, the test continues into the receive loop even when send already failed, which adds secondary failures and latency.
Proposed fix
result = client.send_message(msg, bound_ep); CHECK(result == Result::SUCCESS, "send_message"); + if (result != Result::SUCCESS) { + client.stop(); + server.stop(); + return; + } MessagePtr received = nullptr;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/tests/test_transport/src/main.cpp` around lines 71 - 80, The test continues into the receive loop even when client.send_message failed; short-circuit immediately after checking result to avoid cascading failures by adding an early exit when result != Result::SUCCESS (i.e., after the CHECK(result == Result::SUCCESS, "send_message") evaluate result and if it indicates failure, return from the test or skip the receive_message loop). Update the logic around client.send_message, result, CHECK, and the subsequent server.receive_message/MessagePtr receive loop so the receive loop only runs when send_message succeeded.include/platform/thread.h (1)
70-79:⚠️ Potential issue | 🔴 Critical
ConditionVariableAPI is not cross-platform compatible as currently defined.Zephyr exposes
wait(Mutex&), but host aliases tostd::condition_variable(which requiresstd::unique_lock<std::mutex>&). This breaks the abstraction contract.#!/bin/bash # Verify actual wait() call style used by platform::ConditionVariable call sites. # Expected: one consistent API style should compile on both host and Zephyr. rg -nP --type=cpp -C2 '\b\.wait\s*\(' rg -nP --type=cpp --type=h '\bplatform::ConditionVariable\b' -C2Also applies to: 171-172
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/thread.h` around lines 70 - 79, The ConditionVariable API currently exposes wait(Mutex& mtx) and wait(Mutex& mtx, Pred pred) which matches Zephyr's k_condvar_wait but breaks host builds that use std::condition_variable requiring std::unique_lock<std::mutex>&; update the ConditionVariable interface to use a single consistent signature (e.g., wait(std::unique_lock<MutexType>&) or make wait take a lock-wrapper type) and adapt the Zephyr backend to accept that lock by extracting the native mutex handle (modify ConditionVariable::wait overloads and their implementations such as wait(Mutex& mtx), wait(Mutex& mtx, Pred) and any usage of mtx.native_handle()) so all call sites compile on both host and Zephyr; ensure the predicate overload accepts the same lock type (reference to lock) and update callers to pass the appropriate lock object.zephyr/CMakeLists.txt (1)
91-94: 🧹 Nitpick | 🔵 TrivialRemove the redundant
CONFIG_SOMEIPcheck in this nested source block.The outer
if(CONFIG_SOMEIP)already guarantees this branch, sozephyr_library_sources_ifdef(CONFIG_SOMEIP ...)is unnecessary here.♻️ Proposed simplification
if(NOT CONFIG_ARCH_POSIX) # Embedded targets only (S32K344, S32K388, etc.) - zephyr_library_sources_ifdef(CONFIG_SOMEIP + zephyr_library_sources( ${SOMEIP_SRC}/platform/zephyr_thread.cpp ${SOMEIP_SRC}/platform/zephyr_memory.cpp ) endif()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@zephyr/CMakeLists.txt` around lines 91 - 94, Inside the existing if(CONFIG_SOMEIP) block remove the redundant conditional form zephyr_library_sources_ifdef(CONFIG_SOMEIP ...) and add the sources unconditionally for that block (i.e., use zephyr_library_sources with ${SOMEIP_SRC}/platform/zephyr_thread.cpp and ${SOMEIP_SRC}/platform/zephyr_memory.cpp) so the nested CONFIG_SOMEIP check is eliminated; update the call that references zephyr_library_sources_ifdef to zephyr_library_sources and keep the same source variables.src/transport/udp_transport.cpp (1)
33-37: Silent no-op when exceptions are disabled leavesUdpTransportin an invalid state.On Zephyr (no exceptions), an invalid
local_endpoint_is silently accepted.start()(Line 119) doesn't re-validate the endpoint beforecreate_socket()/bind_socket(), so the failure surfaces late with an unhelpfulNETWORK_ERROR.Proposed fix — validate in start()
Result UdpTransport::start() { if (is_running()) { return Result::SUCCESS; } + if (!local_endpoint_.is_valid()) { + return Result::INVALID_ENDPOINT; + } + Result result = create_socket();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/udp_transport.cpp` around lines 33 - 37, The constructor/initializer currently leaves UdpTransport::local_endpoint_ invalid when exceptions are disabled; update UdpTransport::start() to re-validate local_endpoint_ before calling create_socket() and bind_socket(), and return/propagate a clear error (or set an appropriate error state) instead of letting create_socket()/bind_socket() fail later with NETWORK_ERROR; specifically add a check in start() that mirrors the constructor's validation of local_endpoint_ and handle the no-exceptions build by returning a failure/error code or setting the transport to an error state so callers get a meaningful failure instead of a silent no-op.src/transport/tcp_transport.cpp (1)
585-588: Useplatform::allocate_message()instead ofstd::make_shared<Message>().Same issue as in
udp_transport.cpp— this bypasses the Zephyr slab allocator on embedded targets.♻️ Proposed fix
Add the include at the top of the file:
`#include` "platform/memory.h"Then apply:
- message = std::make_shared<Message>(); - if (message && message->deserialize(message_data)) { + message = platform::allocate_message(); + if (message && message->deserialize(message_data)) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/tcp_transport.cpp` around lines 585 - 588, Replace the direct heap allocation of Message with the platform slab allocator: include "platform/memory.h", call platform::allocate_message() instead of std::make_shared<Message>() to obtain message, and then call message->deserialize(message_data) as before; ensure you preserve the same nullptr check and return true when deserialize succeeds. Use the existing variable name message and the deserialize method to locate the spot to change.include/platform/memory.h (1)
36-42: Add arelease_messagestub on the non-Zephyr path for API symmetry.The Zephyr branch declares both
allocate_message()andrelease_message(), but the#elsebranch only definesallocate_message(). Any portable code callingplatform::release_message()will fail to compile on the host path.♻️ Proposed fix
`#else` inline MessagePtr allocate_message() { return std::make_shared<Message>(); } +inline void release_message(Message* /* msg */) { + // No-op: shared_ptr handles deletion on non-embedded targets. +} + `#endif`🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@include/platform/memory.h` around lines 36 - 42, The non-Zephyr branch defines allocate_message() but is missing a release_message() stub, breaking calls to platform::release_message() on host builds; add an inline release_message function in the same branch with the same signature used by the Zephyr path (e.g., inline void release_message(MessagePtr) or inline void release_message(const MessagePtr&) that accepts the MessagePtr/Message type and is a no-op) so API symmetry is preserved alongside the existing inline MessagePtr allocate_message().src/platform/zephyr_memory.cpp (2)
62-66: Verifyk_mem_slab_freesignature matches your target Zephyr version.The call passes
msgasvoid*. Zephyr ≥ 3.5 expectsvoid*, but older versions (used in some CI images likev0.27.4) expectvoid**. Passing the wrong type causes silent memory corruption.#!/bin/bash # Check which Zephyr SDK/version is referenced in CI and build configs rg -n "zephyr" --include="*.yml" --include="*.yaml" --include="Dockerfile*" --include="*.txt" -C2 | grep -iE "version|tag|image|sdk|v[0-9]"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/platform/zephyr_memory.cpp` around lines 62 - 66, The release_message function calls k_mem_slab_free with msg which may be the wrong pointer type for some Zephyr versions; inspect the k_mem_slab_free signature your build uses and pass the correct type—if your Zephyr expects void* (>=3.5) keep passing msg, if it expects void** (older CI images) pass a pointer-to-pointer (address of the Message* variable) instead; update release_message (and any callers) to match message_slab and Message usage and consider adding a small compile-time wrapper or `#if` check around k_mem_slab_free to choose between k_mem_slab_free(&message_slab, msg) and k_mem_slab_free(&message_slab, &msg) so the correct signature is used.
21-22: Usealignof(someip::Message)instead of hardcoded__aligned(8).
Messagecontainsstd::vector,std::optional, andstd::chrono::time_point— their required alignment may exceed 8 on some architectures. Placement-new on an insufficiently aligned buffer is undefined behavior.Proposed fix
-static char message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)] - __aligned(8); +static char __aligned(alignof(someip::Message)) + message_pool_buffer[CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/platform/zephyr_memory.cpp` around lines 21 - 22, The buffer message_pool_buffer is aligned with a fixed __aligned(8), which can be insufficient for someip::Message (contains vector/optional/time_point) and leads to UB on placement-new; replace the hardcoded alignment by applying alignas(alignof(someip::Message)) to message_pool_buffer (keeping its size expression using CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)) so the array is properly aligned for constructing someip::Message instances.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Dockerfile.zephyr`:
- Around line 48-56: Replace the ad-hoc directory changes in the RUN steps with
explicit WORKDIR instructions: set WORKDIR /workspace/zephyrproject before
running the west init/update/zephyr-export sequence (so the RUN that invokes
west init, west update --narrow -o=--depth=1 and west zephyr-export runs from
the correct directory), and set WORKDIR /workspace/zephyrproject/tools/net-tools
before running the make step (so the RUN make executes in tools/net-tools);
update or add WORKDIR lines instead of using `cd` in RUN to satisfy
Hadolint/Dockle/Trivy rules and keep commands unchanged.
- Line 23: The Dockerfile's ARG ZEPHYR_SDK_VERSION is set to 0.16.8 which
mismatches the CI workflow; update ARG ZEPHYR_SDK_VERSION to 0.17.0 so the
computed ZEPHYR_SDK_INSTALL_DIR and any references to the SDK match
.github/workflows/zephyr.yml (change the value of the ARG declaration
ZEPHYR_SDK_VERSION from "0.16.8" to "0.17.0").
In `@include/platform/net.h`:
- Around line 123-130: Change the socket parameter types in
someip_set_nonblocking and someip_set_blocking from int to SOCKET and propagate
the SOCKET type to transport socket fields: replace int socket_fd_ in
UdPTransport (udp_transport) and int listen_socket_fd_ in TcPTransport
(tcp_transport) with SOCKET socket_fd_ / SOCKET listen_socket_fd_. Update all
code that compares or initializes these fields to use INVALID_SOCKET instead of
numeric checks (>=0, <0, != -1) and initialize to INVALID_SOCKET where
appropriate so ioctlsocket() receives an untruncated SOCKET on Win64.
In `@include/platform/thread.h`:
- Around line 105-121: The join() path currently leaves ctx_ allocated and
callable state stale so the destructor skips cleanup; update Thread::join() (and
the same logic at the other occurrence) to, after successful
k_thread_join(&thread_, K_FOREVER), delete ctx_, set ctx_ = nullptr and update
lifecycle flags (e.g. started_ = false; joined_ = true) so the thread context is
freed and no stale callable remains; ensure the change mirrors the destructor's
cleanup semantics to avoid double-free or leaving dangling state.
In `@scripts/run_zephyr_tests.sh`:
- Around line 86-89: The s32k388_renode case currently calls run_test and falls
through to the generic else branch which marks builds as PASSED without running
Renode; update the s32k388_renode case to either invoke the Renode runner or
explicitly mark it build-only: replace the current block for s32k388_renode so
it calls the Renode test helper (e.g., run_renode_test.sh or the script/function
used elsewhere for mr_canhubk3) with the same test paths, or set
MODE="--build-only" before calling run_test if you mean to only build; ensure
you modify the s32k388_renode case (not the generic else) so run_test or
run_renode_test is executed appropriately.
In `@src/sd/sd_server.cpp`:
- Around line 282-285: The offer timer thread currently does a single long
platform::this_thread::sleep_for(next_offer_delay_) which makes stopping block
until that sleep finishes; change the thread body for offer_timer_thread_ (and
the analogous timer thread at the other site) to wait on a
std::condition_variable (or platform waitable timer) with a timed wait (e.g.,
cv.wait_for/mutex + predicate checking running_) instead of sleep_for, and when
shutting down set running_ = false and call cv.notify_one() before join() so the
thread wakes immediately and exits promptly; update the thread lambda to use the
condition variable and predicate rather than a single long sleep to ensure
join() does not block for the full next_offer_delay_.
In `@src/transport/endpoint.cpp`:
- Line 18: The include <cstring> in src/transport/endpoint.cpp is unused; remove
the unused header line so the file no longer includes <cstring> (no changes to
any functions or classes in endpoint.cpp are needed).
- Around line 216-245: The IPv6 compressed-address parsing incorrectly treats
the two zero-length segments from "::" as an error; in the loop that scans
segments (using pos, next, len, double_colon, groups) detect the compression
branch when len == 0 and pos == double_colon and advance pos past both colons
(i.e., skip the adjacent empty segment so the next iteration doesn't immediately
fail), instead of only accepting the first empty segment; also change the final
validation for compression (the has_double_colon branch) to allow groups >= 0
(so "::" is valid), and remove or stop using the dead variable compression_used
(or repurpose it if needed). Ensure these changes are applied around the while
loop and the final groups check in the function that validates IPv6 addresses.
In `@zephyr/samples/net_test/prj.conf`:
- Around line 14-15: The config currently hardcodes endpoint IPs via
CONFIG_NET_CONFIG_MY_IPV4_ADDR and CONFIG_NET_CONFIG_PEER_IPV4_ADDR; replace
this by making the addresses configurable at build/run time — remove the fixed
literals from prj.conf and instead expose these as build-time variables (e.g.,
set defaults in Kconfig or leave unset and inject values via board overlays,
CMake -D options, or environment-backed config fragments) so each
test/simulation can supply distinct IPv4 addresses per scenario using the board
overlay names or CMake variable names that map to CONFIG_NET_CONFIG_MY_IPV4_ADDR
and CONFIG_NET_CONFIG_PEER_IPV4_ADDR.
In `@zephyr/tests/test_core/src/main.cpp`:
- Line 94: The sequential-ID assertion can fail on uint16_t wraparound; change
the comparison to perform the increment in the same uint16_t domain so
wraparound is handled, e.g. compare s2 against static_cast<uint16_t>(s1 + 1) (or
static_cast<uint16_t>(static_cast<uint16_t>(s1) + 1)) inside the CHECK call that
uses s1, s2 and the "sequential_ids" tag so the intent is explicit and safe if
IDs wrap at 0xFFFF.
---
Outside diff comments:
In `@src/events/event_subscriber.cpp`:
- Around line 97-122: The code currently holds platform::ScopedLock
subscriptions_mutex_ while calling transport_->send_message, which risks
blocking and deadlocks; change the lock scope in the subscribe flow (the block
using platform::ScopedLock subs_lock, make_subscription_key, and subscriptions_
assignment) so you only hold the mutex for creating the key and inserting
subscriptions_[key] = sub_info, then release the lock before calling
transport_->send_message(service_endpoint); if send_message fails, re-acquire
subscriptions_mutex_ and erase subscriptions_. Apply the same change to the
analogous section referenced at lines 130-158 to avoid holding
subscriptions_mutex_ across network I/O.
- Around line 261-279: Currently the code calls
sub_info.notification_callback(notification) while holding subscriptions_mutex_,
which risks deadlock if callbacks re-enter subscriber APIs; modify OnReceive (or
the function containing this loop) to collect the EventNotification objects and
corresponding callbacks (e.g., pairs of EventNotification and
sub_info.notification_callback) into a local vector while holding
subscriptions_mutex_ and then release subscriptions_mutex_ and invoke each
callback from that vector; use the existing symbols subscriptions_mutex_,
subscriptions_, sub_info.notification_callback, and EventNotification to locate
and implement the change.
In `@src/rpc/rpc_client.cpp`:
- Around line 174-190: cancel_call and on_message_received currently invoke user
callbacks while holding pending_calls_mutex_, risking deadlock if callbacks call
back into RpcClient; fix by extracting the callback (and any data needed to
build RpcResponse) and erasing the pending_calls_ entry while holding
pending_calls_mutex_, then release the lock and invoke the callback outside the
lock. Specifically, in cancel_call and in on_message_received: grab
it->second.callback (and session/service/method ids or build RpcResponse data)
into local variables, erase the map entry under pending_calls_mutex_, drop the
lock, then call the saved callback; ensure you still construct RpcResponse using
the saved data before invoking the callback.
In `@src/sd/sd_client.cpp`:
- Around line 373-394: subscriptions_mutex_ is held too long around the
pending_finds_ work; narrow its scope so we don't hold subscriptions_mutex_
while acquiring pending_finds_mutex_. Specifically, in the block that references
service_subscriptions_ (use service_subscriptions_.find(instance.service_id) and
sub_it->second.available_callback), acquire platform::ScopedLock
lock(subscriptions_mutex_) only for the lookup/callback retrieval, copy the
available_callback (and any needed data like instance or a small flag) out while
holding the lock, then release it before entering the block that acquires
platform::ScopedLock lock(pending_finds_mutex_) to iterate pending_finds_ and
call their callbacks; ensure you copy any callback objects (available_callback
and pending find callbacks) out of their containers before invoking them to
avoid use-after-release races.
- Around line 270-284: Replace the RTTI-dependent std::dynamic_pointer_cast
calls with std::static_pointer_cast for Zephyr compatibility: in
join_multicast_group() and leave_multicast_group() cast transport_ to
std::static_pointer_cast<transport::UdpTransport>(transport_) (refer to
join_multicast_group, leave_multicast_group, transport_, and
transport::UdpTransport) and keep or remove the subsequent null checks as
desired since transport_ is always constructed as UdpTransport; ensure the
return/conditional logic still calls join_multicast_group("224.224.224.245") and
leave_multicast_group("224.224.224.245") on the resulting pointer.
In `@src/sd/sd_server.cpp`:
- Around line 92-98: In shutdown(), the offered_services_mutex_ is held while
calling leave_multicast_group() and transport_->stop(), risking deadlock if
those stop paths invoke callbacks that need the same mutex; fix by narrowing the
lock scope: acquire platform::ScopedLock around offered_services_.clear() only
(or use a short scope/block), then release the mutex before calling
leave_multicast_group() and transport_->stop() so those functions run without
holding offered_services_mutex_.
In `@src/transport/endpoint.cpp`:
- Around line 71-73: The check "if (port_ > 65535)" is tautological because
port_ is uint16_t; remove this dead branch in src/transport/endpoint.cpp (the
check around the port_ member). If you intended to accept/validate values
>65535, either change the port_ storage type (e.g., to uint32_t) or validate the
original input before casting/assigning to port_ (e.g., in the constructor or
setPort method) so you don't rely on an impossible comparison against port_
itself.
In `@src/transport/udp_transport.cpp`:
- Around line 341-348: Replace the heap allocation of a Message in the receive
path with the Zephyr slab allocator: include "platform/memory.h" at the top of
the file and use platform::allocate_message() instead of
std::make_shared<Message>() when constructing MessagePtr (the variable named
message) before deserializing; keep the existing deserialize,
platform::ScopedLock on queue_mutex_, and receive_queue_.push(message) logic
unchanged so messages come from the pre-allocated pool.
---
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 35-39: The "Init Zephyr" step is duplicated; extract it into a
reusable composite GitHub Action (e.g., create a composite action named
init-zephyr with the steps pip install jsonschema, west init /tmp/zp && cd
/tmp/zp, and west update --narrow -o=--depth=1 && west zephyr-export) and then
replace the inline step (the step with name "Init Zephyr") with a single uses:
./path-to-init-zephyr or uses: org/repo/.github/actions/init-zephyr@ref,
ensuring inputs/outputs and permissions match the original behavior.
- Around line 30-34: The "Install Zephyr SDK" step is downloading and extracting
the SDK without verifying integrity; update that GitHub Actions step (and the
similar step at lines 67-73) to download the official checksum (or
.sha256/.sha256sum) for zephyr-sdk-0.17.0, verify the archive with sha256sum (or
gpg/secure signing if available) and only extract if the checksum matches,
failing the job on mismatch; reference the "Install Zephyr SDK" job/step name to
locate where to add the checksum download and verification logic.
- Line 19: The workflow line containing the cmake invocation (the token "cmake
--build build -j$(nproc)") risks word-splitting; update that command to quote
the command substitution (e.g., use -j"$(nproc)") so the "-j" argument receives
a single value and avoids shellcheck SC2046/actionlint warnings; locate the
invocation of cmake in the zephyr.yml workflow and replace the unquoted $(nproc)
usage with a quoted form.
In `@docs/ZEPHYR_PORT_PROGRESS.md`:
- Line 6: The header term "**Targets**" in docs/ZEPHYR_PORT_PROGRESS.md is in
English; change it to a Portuguese equivalent (e.g., "**Alvos**" or
"**Plataformas**") so the document remains consistent in Portuguese, updating
the line that currently reads "**Targets**: native_sim, mr_canhubk3 (S32K344),
s32k388_renode (S32K388)" to use the chosen Portuguese term.
- Around line 26-28: The note claiming CONFIG_REQUIRES_FULL_LIBCPP replaces
CONFIG_NEWLIB_LIBC is incorrect; update the text in ZEPHYR_PORT_PROGRESS.md to
remove or reword that sentence and explicitly state the correct relationship:
CONFIG_REQUIRES_FULL_LIBCPP enables the full C++ library, whereas
CONFIG_NEWLIB_LIBC (and the NEWLIB_LIBC/EXTERNAL_LIBC Kconfig symbols) control
which C library is used on native_sim; mention that NEWLIB_LIBC conflicts with
EXTERNAL_LIBC on native_sim and that CONFIG_REQUIRES_FULL_LIBCPP does not
substitute for CONFIG_NEWLIB_LIBC.
In `@include/platform/memory.h`:
- Around line 36-42: The non-Zephyr branch defines allocate_message() but is
missing a release_message() stub, breaking calls to platform::release_message()
on host builds; add an inline release_message function in the same branch with
the same signature used by the Zephyr path (e.g., inline void
release_message(MessagePtr) or inline void release_message(const MessagePtr&)
that accepts the MessagePtr/Message type and is a no-op) so API symmetry is
preserved alongside the existing inline MessagePtr allocate_message().
In `@include/platform/thread.h`:
- Around line 70-79: The ConditionVariable API currently exposes wait(Mutex&
mtx) and wait(Mutex& mtx, Pred pred) which matches Zephyr's k_condvar_wait but
breaks host builds that use std::condition_variable requiring
std::unique_lock<std::mutex>&; update the ConditionVariable interface to use a
single consistent signature (e.g., wait(std::unique_lock<MutexType>&) or make
wait take a lock-wrapper type) and adapt the Zephyr backend to accept that lock
by extracting the native mutex handle (modify ConditionVariable::wait overloads
and their implementations such as wait(Mutex& mtx), wait(Mutex& mtx, Pred) and
any usage of mtx.native_handle()) so all call sites compile on both host and
Zephyr; ensure the predicate overload accepts the same lock type (reference to
lock) and update callers to pass the appropriate lock object.
In `@scripts/run_renode_test.sh`:
- Around line 55-56: The current renode invocation uses a fixed "start; sleep
10; quit" which always exits 0 and doesn't propagate test failures; change this
so the test runner reports and propagates an actual exit code: update the renode
command that uses RENODE_SCRIPT and ELF_PATH (the line with renode --disable-xwt
-e "... start; sleep 10; quit") to either (a) have the RENODE_SCRIPT write the
test result/exit code to a sentinel file and have the shell wait for that file
and then exit with that code, or (b) have the script call renode's exit <code>
inside the -e script instead of quit and let the shell capture renode's non-zero
exit status—remove the fixed sleep and ensure the final shell exit uses the
propagated test exit code.
In `@src/platform/zephyr_memory.cpp`:
- Around line 62-66: The release_message function calls k_mem_slab_free with msg
which may be the wrong pointer type for some Zephyr versions; inspect the
k_mem_slab_free signature your build uses and pass the correct type—if your
Zephyr expects void* (>=3.5) keep passing msg, if it expects void** (older CI
images) pass a pointer-to-pointer (address of the Message* variable) instead;
update release_message (and any callers) to match message_slab and Message usage
and consider adding a small compile-time wrapper or `#if` check around
k_mem_slab_free to choose between k_mem_slab_free(&message_slab, msg) and
k_mem_slab_free(&message_slab, &msg) so the correct signature is used.
- Around line 21-22: The buffer message_pool_buffer is aligned with a fixed
__aligned(8), which can be insufficient for someip::Message (contains
vector/optional/time_point) and leads to UB on placement-new; replace the
hardcoded alignment by applying alignas(alignof(someip::Message)) to
message_pool_buffer (keeping its size expression using
CONFIG_SOMEIP_MESSAGE_POOL_SIZE * sizeof(someip::Message)) so the array is
properly aligned for constructing someip::Message instances.
In `@src/sd/sd_server.cpp`:
- Line 202: The multicast port is being pre-byte-swapped before serialization;
remove the call to someip_htons and pass the raw config_.multicast_port into
multicast_option->set_port so the option serialization does the correct
byte-ordering (i.e., replace
multicast_option->set_port(someip_htons(config_.multicast_port)) with passing
config_.multicast_port directly).
In `@src/transport/endpoint.cpp`:
- Around line 15-19: The previous missing header for character classification
has been fixed by adding <cctype> to the include list; confirm that functions
like isspace/isdigit (or other ctype functions used by code in
src/transport/endpoint.cpp) now compile and keep the new `#include` <cctype> in
place, removing no other includes or changes.
In `@src/transport/tcp_transport.cpp`:
- Around line 585-588: Replace the direct heap allocation of Message with the
platform slab allocator: include "platform/memory.h", call
platform::allocate_message() instead of std::make_shared<Message>() to obtain
message, and then call message->deserialize(message_data) as before; ensure you
preserve the same nullptr check and return true when deserialize succeeds. Use
the existing variable name message and the deserialize method to locate the spot
to change.
In `@src/transport/udp_transport.cpp`:
- Around line 33-37: The constructor/initializer currently leaves
UdpTransport::local_endpoint_ invalid when exceptions are disabled; update
UdpTransport::start() to re-validate local_endpoint_ before calling
create_socket() and bind_socket(), and return/propagate a clear error (or set an
appropriate error state) instead of letting create_socket()/bind_socket() fail
later with NETWORK_ERROR; specifically add a check in start() that mirrors the
constructor's validation of local_endpoint_ and handle the no-exceptions build
by returning a failure/error code or setting the transport to an error state so
callers get a meaningful failure instead of a silent no-op.
In `@zephyr/CMakeLists.txt`:
- Around line 91-94: Inside the existing if(CONFIG_SOMEIP) block remove the
redundant conditional form zephyr_library_sources_ifdef(CONFIG_SOMEIP ...) and
add the sources unconditionally for that block (i.e., use zephyr_library_sources
with ${SOMEIP_SRC}/platform/zephyr_thread.cpp and
${SOMEIP_SRC}/platform/zephyr_memory.cpp) so the nested CONFIG_SOMEIP check is
eliminated; update the call that references zephyr_library_sources_ifdef to
zephyr_library_sources and keep the same source variables.
In `@zephyr/samples/hello_s32k/prj.conf`:
- Line 6: The pr sets CONFIG_MAIN_STACK_SIZE=2048 in the hello_s32k sample which
appears lower than other Zephyr SOME/IP C++ samples and may be insufficient for
libc++ startup; verify that hello_s32k is an outlier by comparing
CONFIG_MAIN_STACK_SIZE across samples (as suggested) and, if confirmed, increase
CONFIG_MAIN_STACK_SIZE in the hello_s32k prj.conf to match the common value used
by other samples (e.g., 4096 or 8192) so the C++ runtime has adequate headroom;
update the prj.conf entry CONFIG_MAIN_STACK_SIZE accordingly and rerun the
sample build/tests to confirm no stack-related failures.
In `@zephyr/samples/net_test/prj.conf`:
- Around line 17-18: The base sample currently enables CONFIG_NET_SHELL
unconditionally; leave CONFIG_NET_LOG_LEVEL_INF in the base prj.conf but remove
CONFIG_NET_SHELL from the base and add it to a debug/bring-up overlay so shell
support is only enabled for debug builds (e.g., create a debug overlay file and
set CONFIG_NET_SHELL=y there). Update/remove the CONFIG_NET_SHELL line in the
base prj.conf and add the same symbol to your debug/bring-up overlay file used
during development; ensure the overlay filename matches your project's debug
overlay convention so the shell is only built for debug/bring-up configurations.
- Around line 20-29: The shared sample prj.conf contains aggressive,
board-specific knobs (CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT,
CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT, CONFIG_NET_MAX_CONTEXTS,
CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_BUF_TX_COUNT, CONFIG_NET_PKT_RX_COUNT,
CONFIG_NET_PKT_TX_COUNT, CONFIG_HEAP_MEM_POOL_SIZE, CONFIG_MAIN_STACK_SIZE);
remove these entries from zephyr/samples/net_test/prj.conf and relocate them
into the appropriate board-specific overlay or per-board prj.conf so only
targets that need the higher network/memory limits opt in; ensure any boards
left without these overrides still build with safe defaults and document the new
per-board override names so maintainers know where to tune them.
In `@zephyr/tests/test_core/prj.conf`:
- Around line 1-3: The test config now correctly includes
CONFIG_REQUIRES_FULL_LIBCPP=y alongside CONFIG_STD_CPP17=y and CONFIG_CPP=y, so
no code changes are required; confirm the presence of the
CONFIG_REQUIRES_FULL_LIBCPP flag in the prj.conf (look for the
CONFIG_REQUIRES_FULL_LIBCPP, CONFIG_STD_CPP17, and CONFIG_CPP entries) and
approve/merge the change.
In `@zephyr/tests/test_transport/src/main.cpp`:
- Around line 71-80: The test continues into the receive loop even when
client.send_message failed; short-circuit immediately after checking result to
avoid cascading failures by adding an early exit when result != Result::SUCCESS
(i.e., after the CHECK(result == Result::SUCCESS, "send_message") evaluate
result and if it indicates failure, return from the test or skip the
receive_message loop). Update the logic around client.send_message, result,
CHECK, and the subsequent server.receive_message/MessagePtr receive loop so the
receive loop only runs when send_message succeeded.
|
|
||
| FROM ghcr.io/zephyrproject-rtos/ci:v0.27.4 | ||
|
|
||
| ARG ZEPHYR_SDK_VERSION=0.16.8 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check Dockerfile SDK version declaration
echo "=== Dockerfile SDK version ==="
rg -n "ZEPHYR_SDK_VERSION" Dockerfile.zephyr
echo ""
echo "=== Workflow SDK version references ==="
rg -n "zephyr-sdk\|ZEPHYR_SDK" .github/workflows/zephyr.yml
echo ""
echo "=== How SDK_VERSION is used in Dockerfile ==="
rg -n "ZEPHYR_SDK" Dockerfile.zephyrRepository: vtz/opensomeip
Length of output: 400
🏁 Script executed:
#!/bin/bash
# List all files in .github/workflows/
echo "=== Workflow files available ==="
fd . .github/workflows/ 2>/dev/null || echo "Directory not found"
echo ""
# Search entire repo for SDK 0.17.0 or 0.16.8
echo "=== All references to SDK versions in repo ==="
rg "0\.17\.0|0\.16\.8" --type-list | head -20
echo ""
echo "=== Search for SDK references in workflows (broader) ==="
find .github -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -10Repository: vtz/opensomeip
Length of output: 1123
🏁 Script executed:
#!/bin/bash
echo "=== Contents of .github/workflows/zephyr.yml ==="
cat .github/workflows/zephyr.yml
echo ""
echo "=== Check Dockerfile.zephyr base image ==="
head -5 Dockerfile.zephyrRepository: vtz/opensomeip
Length of output: 3756
Update Dockerfile SDK version to match CI workflow.
The Dockerfile defaults ZEPHYR_SDK_VERSION=0.16.8 (used in ZEPHYR_SDK_INSTALL_DIR at line 60), but .github/workflows/zephyr.yml explicitly installs and references SDK 0.17.0. This version mismatch means the Dockerfile will point to a non-existent SDK path unless the build arg is overridden.
Suggested fix
-ARG ZEPHYR_SDK_VERSION=0.16.8
+ARG ZEPHYR_SDK_VERSION=0.17.0📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ARG ZEPHYR_SDK_VERSION=0.16.8 | |
| ARG ZEPHYR_SDK_VERSION=0.17.0 |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Dockerfile.zephyr` at line 23, The Dockerfile's ARG ZEPHYR_SDK_VERSION is set
to 0.16.8 which mismatches the CI workflow; update ARG ZEPHYR_SDK_VERSION to
0.17.0 so the computed ZEPHYR_SDK_INSTALL_DIR and any references to the SDK
match .github/workflows/zephyr.yml (change the value of the ARG declaration
ZEPHYR_SDK_VERSION from "0.16.8" to "0.17.0").
| # Initialize Zephyr workspace with west | ||
| RUN west init /workspace/zephyrproject && \ | ||
| cd /workspace/zephyrproject && \ | ||
| west update --narrow -o=--depth=1 && \ | ||
| west zephyr-export | ||
|
|
||
| # Build Zephyr net-tools for TAP interface support | ||
| RUN cd /workspace/zephyrproject/tools/net-tools && \ | ||
| make |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Prefer WORKDIR over RUN cd ... for directory changes.
Lines 49-52 and 55-56 use RUN cd ... which is flagged by Trivy (DS-0013) and Hadolint (DL3003). While functionally correct within a single RUN, using WORKDIR is the idiomatic Docker approach.
Suggested refactor
-# Initialize Zephyr workspace with west
-RUN west init /workspace/zephyrproject && \
- cd /workspace/zephyrproject && \
- west update --narrow -o=--depth=1 && \
- west zephyr-export
+# Initialize Zephyr workspace with west
+RUN west init /workspace/zephyrproject
+WORKDIR /workspace/zephyrproject
+RUN west update --narrow -o=--depth=1 && \
+ west zephyr-export
# Build Zephyr net-tools for TAP interface support
-RUN cd /workspace/zephyrproject/tools/net-tools && \
- make
+WORKDIR /workspace/zephyrproject/tools/net-tools
+RUN make
+
+WORKDIR /workspace📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Initialize Zephyr workspace with west | |
| RUN west init /workspace/zephyrproject && \ | |
| cd /workspace/zephyrproject && \ | |
| west update --narrow -o=--depth=1 && \ | |
| west zephyr-export | |
| # Build Zephyr net-tools for TAP interface support | |
| RUN cd /workspace/zephyrproject/tools/net-tools && \ | |
| make | |
| # Initialize Zephyr workspace with west | |
| RUN west init /workspace/zephyrproject | |
| WORKDIR /workspace/zephyrproject | |
| RUN west update --narrow -o=--depth=1 && \ | |
| west zephyr-export | |
| # Build Zephyr net-tools for TAP interface support | |
| WORKDIR /workspace/zephyrproject/tools/net-tools | |
| RUN make | |
| WORKDIR /workspace |
🧰 Tools
🪛 Hadolint (2.14.0)
[warning] 49-49: Use WORKDIR to switch to a directory
(DL3003)
[warning] 55-55: Use WORKDIR to switch to a directory
(DL3003)
🪛 Trivy (0.69.1)
[warning] 55-56: 'RUN cd ...' to change directory
RUN should not be used to change directory: 'cd /workspace/zephyrproject/tools/net-tools && make'. Use 'WORKDIR' statement instead.
Rule: DS-0013
(IaC/Dockerfile)
[warning] 49-52: 'RUN cd ...' to change directory
RUN should not be used to change directory: 'west init /workspace/zephyrproject && cd /workspace/zephyrproject && west update --narrow -o=--depth=1 && west zephyr-export'. Use 'WORKDIR' statement instead.
Rule: DS-0013
(IaC/Dockerfile)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Dockerfile.zephyr` around lines 48 - 56, Replace the ad-hoc directory changes
in the RUN steps with explicit WORKDIR instructions: set WORKDIR
/workspace/zephyrproject before running the west init/update/zephyr-export
sequence (so the RUN that invokes west init, west update --narrow -o=--depth=1
and west zephyr-export runs from the correct directory), and set WORKDIR
/workspace/zephyrproject/tools/net-tools before running the make step (so the
RUN make executes in tools/net-tools); update or add WORKDIR lines instead of
using `cd` in RUN to satisfy Hadolint/Dockle/Trivy rules and keep commands
unchanged.
| static inline int someip_set_nonblocking(int fd) { | ||
| u_long mode = 1; | ||
| return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? 0 : -1; | ||
| } | ||
| static inline int someip_set_blocking(int fd) { | ||
| u_long mode = 0; | ||
| return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? 0 : -1; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify socket-handle type consistency across Windows paths.
# Check current socket field types in transport headers
echo "=== Socket field types in transport headers ==="
rg -n 'socket_fd_|listen_socket_fd_' --type=cpp --type=h -B2 -A2
echo -e "\n=== Function signatures for someip_set_nonblocking/blocking ==="
rg -n 'someip_set_(nonblocking|blocking)' --type=cpp --type=h -B2 -A5
echo -e "\n=== SOCKET type definition ==="
rg -n 'typedef.*SOCKET|#define.*SOCKET' --type=cpp --type=h
echo -e "\n=== ioctlsocket calls in the codebase ==="
rg -n 'ioctlsocket' --type=cpp --type=h -B2 -A2Repository: vtz/opensomeip
Length of output: 16389
🏁 Script executed:
#!/bin/bash
# Check Windows headers and socket creation
echo "=== Windows headers includes ==="
rg -n '#include.*[wW]insock|#include.*[Ww]indows' --type=cpp --type=h
echo -e "\n=== Socket creation on Windows ==="
rg -n 'socket\s*\(' --type=cpp --type=h -B2 -A2 | head -50
echo -e "\n=== Check platform/net.h full content ==="
cat -n include/platform/net.h | head -150Repository: vtz/opensomeip
Length of output: 8887
Use SOCKET for Windows socket handles throughout the transport layer, not just in these helpers.
The Windows socket() function returns a SOCKET type (pointer-sized on Win64), but transport code stores it in int socket_fd_ fields. Passing truncated int values to ioctlsocket() breaks nonblocking/blocking mode changes on Win64.
Change these function signatures from int fd to SOCKET fd, and change socket field types in transport headers:
include/transport/udp_transport.hline 90: changeint socket_fd_toSOCKET socket_fd_include/transport/tcp_transport.hline 202: changeint listen_socket_fd_toSOCKET listen_socket_fd_
Proposed changes
include/platform/net.h (lines 123–130):
`#if` defined(_WIN32)
-static inline int someip_set_nonblocking(int fd) {
+static inline int someip_set_nonblocking(SOCKET fd) {
u_long mode = 1;
return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? 0 : -1;
}
-static inline int someip_set_blocking(int fd) {
+static inline int someip_set_blocking(SOCKET fd) {
u_long mode = 0;
return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? 0 : -1;
}include/transport/udp_transport.h (line 90):
-int socket_fd_{-1};
+SOCKET socket_fd_{INVALID_SOCKET};include/transport/tcp_transport.h (line 202):
-int listen_socket_fd_{-1};
+SOCKET listen_socket_fd_{INVALID_SOCKET};Also update all comparisons from >= 0 / < 0 / != -1 to use INVALID_SOCKET constant and update initialization values accordingly.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@include/platform/net.h` around lines 123 - 130, Change the socket parameter
types in someip_set_nonblocking and someip_set_blocking from int to SOCKET and
propagate the SOCKET type to transport socket fields: replace int socket_fd_ in
UdPTransport (udp_transport) and int listen_socket_fd_ in TcPTransport
(tcp_transport) with SOCKET socket_fd_ / SOCKET listen_socket_fd_. Update all
code that compares or initializes these fields to use INVALID_SOCKET instead of
numeric checks (>=0, <0, != -1) and initialize to INVALID_SOCKET where
appropriate so ioctlsocket() receives an untruncated SOCKET on Win64.
| ~Thread() { | ||
| if (joinable()) { | ||
| k_thread_abort(&thread_); | ||
| delete ctx_; | ||
| ctx_ = nullptr; | ||
| started_ = false; | ||
| } | ||
| } | ||
|
|
||
| bool joinable() const { return started_ && !joined_; } | ||
|
|
||
| void join() { | ||
| if (joinable()) { | ||
| k_thread_join(&thread_, K_FOREVER); | ||
| joined_ = true; | ||
| } | ||
| } |
There was a problem hiding this comment.
Thread::join() leaks ctx_ and leaves stale callable state.
After a successful join, joined_ becomes true, but ctx_ is never freed; destructor then skips cleanup because joinable() is false.
🐛 Proposed lifecycle fix
~Thread() {
if (joinable()) {
k_thread_abort(&thread_);
- delete ctx_;
- ctx_ = nullptr;
- started_ = false;
}
+ delete ctx_;
+ ctx_ = nullptr;
+ started_ = false;
+ joined_ = true;
}
void join() {
if (joinable()) {
- k_thread_join(&thread_, K_FOREVER);
+ int rc = k_thread_join(&thread_, K_FOREVER);
+ __ASSERT(rc == 0, "k_thread_join failed: %d", rc);
joined_ = true;
+ delete ctx_;
+ ctx_ = nullptr;
}
}Also applies to: 136-139
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@include/platform/thread.h` around lines 105 - 121, The join() path currently
leaves ctx_ allocated and callable state stale so the destructor skips cleanup;
update Thread::join() (and the same logic at the other occurrence) to, after
successful k_thread_join(&thread_, K_FOREVER), delete ctx_, set ctx_ = nullptr
and update lifecycle flags (e.g. started_ = false; joined_ = true) so the thread
context is freed and no stale callable remains; ensure the change mirrors the
destructor's cleanup semantics to avoid double-free or leaving dangling state.
| s32k388_renode) | ||
| run_test test_core "$ZEPHYR_DIR/tests/test_core" s32k388_renode | ||
| run_test hello_s32k "$ZEPHYR_DIR/samples/hello_s32k" s32k388_renode | ||
| ;; |
There was a problem hiding this comment.
s32k388_renode tests are counted as passed without Renode execution.
Unlike mr_canhubk3 which explicitly sets MODE="--build-only", s32k388_renode routes through the else branch at line 60-62 and silently marks builds as PASSED. This gives a misleading test summary. Consider either calling run_renode_test.sh here or explicitly setting MODE="--build-only".
Suggested fix
s32k388_renode)
+ MODE="--build-only"
run_test test_core "$ZEPHYR_DIR/tests/test_core" s32k388_renode
run_test hello_s32k "$ZEPHYR_DIR/samples/hello_s32k" s32k388_renode
;;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| s32k388_renode) | |
| run_test test_core "$ZEPHYR_DIR/tests/test_core" s32k388_renode | |
| run_test hello_s32k "$ZEPHYR_DIR/samples/hello_s32k" s32k388_renode | |
| ;; | |
| s32k388_renode) | |
| MODE="--build-only" | |
| run_test test_core "$ZEPHYR_DIR/tests/test_core" s32k388_renode | |
| run_test hello_s32k "$ZEPHYR_DIR/samples/hello_s32k" s32k388_renode | |
| ;; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/run_zephyr_tests.sh` around lines 86 - 89, The s32k388_renode case
currently calls run_test and falls through to the generic else branch which
marks builds as PASSED without running Renode; update the s32k388_renode case to
either invoke the Renode runner or explicitly mark it build-only: replace the
current block for s32k388_renode so it calls the Renode test helper (e.g.,
run_renode_test.sh or the script/function used elsewhere for mr_canhubk3) with
the same test paths, or set MODE="--build-only" before calling run_test if you
mean to only build; ensure you modify the s32k388_renode case (not the generic
else) so run_test or run_renode_test is executed appropriately.
| offer_timer_thread_ = std::make_unique<platform::Thread>([this]() { | ||
| while (running_) { | ||
| std::this_thread::sleep_for(next_offer_delay_); | ||
| platform::this_thread::sleep_for(next_offer_delay_); | ||
|
|
There was a problem hiding this comment.
Timer thread shutdown is not promptly interruptible.
At Lines 282-285 and 304-305, join() may block for the full next_offer_delay_ because the worker is sleeping in one large chunk.
Proposed fix
offer_timer_thread_ = std::make_unique<platform::Thread>([this]() {
while (running_) {
- platform::this_thread::sleep_for(next_offer_delay_);
+ auto remaining = next_offer_delay_;
+ while (running_ && remaining > std::chrono::milliseconds(0)) {
+ const auto chunk = std::min(remaining, std::chrono::milliseconds(50));
+ platform::this_thread::sleep_for(chunk);
+ remaining -= chunk;
+ }
if (!running_) {
break;
}Also applies to: 304-305
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/sd/sd_server.cpp` around lines 282 - 285, The offer timer thread
currently does a single long platform::this_thread::sleep_for(next_offer_delay_)
which makes stopping block until that sleep finishes; change the thread body for
offer_timer_thread_ (and the analogous timer thread at the other site) to wait
on a std::condition_variable (or platform waitable timer) with a timed wait
(e.g., cv.wait_for/mutex + predicate checking running_) instead of sleep_for,
and when shutting down set running_ = false and call cv.notify_one() before
join() so the thread wakes immediately and exits promptly; update the thread
lambda to use the condition variable and predicate rather than a single long
sleep to ensure join() does not block for the full next_offer_delay_.
| #include <sstream> | ||
| #include <functional> | ||
| #include <cstdlib> | ||
| #include <cstring> |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
<cstring> appears unused — remove it.
No std::memcpy, strlen, strcmp, or any other <cstring> symbol is called in this file.
🧹 Proposed fix
`#include` <cstdlib>
-#include <cstring>
`#include` <cctype>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #include <cstring> | |
| `#include` <cstdlib> | |
| `#include` <cctype> |
🧰 Tools
🪛 Cppcheck (2.19.0)
[information] 18-18: Include file
(missingIncludeSystem)
[information] 18-18: Include file
(missingIncludeSystem)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/transport/endpoint.cpp` at line 18, The include <cstring> in
src/transport/endpoint.cpp is unused; remove the unused header line so the file
no longer includes <cstring> (no changes to any functions or classes in
endpoint.cpp are needed).
| while (pos <= address.size()) { | ||
| size_t next = address.find(':', pos); | ||
| if (next == std::string::npos) { | ||
| next = address.size(); | ||
| } | ||
| size_t len = next - pos; | ||
|
|
||
| if (len > 0) { | ||
| if (len > 4) { | ||
| return false; | ||
| } | ||
| ++groups; | ||
| } else { | ||
| if (has_double_colon && pos == double_colon) { | ||
| compression_used = true; | ||
| } else if (pos > 0 && next < address.size()) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| if (next == address.size()) { | ||
| break; | ||
| } | ||
| pos = next + 1; | ||
| } | ||
|
|
||
| if (has_double_colon) { | ||
| return groups >= 1 && groups <= 7; | ||
| } | ||
| return groups == 8; |
There was a problem hiding this comment.
Critical: :: parsing is broken — virtually all compressed IPv6 addresses are incorrectly rejected.
:: is two consecutive colons; splitting on each : individually produces two adjacent zero-length segments. The loop only whitelists the segment at exactly pos == double_colon; the very next iteration has pos == double_colon + 1 and falls into the else if (pos > 0 && next < address.size()) branch, which returns false unconditionally.
Concrete failures:
| Input | Expected | Actual |
|---|---|---|
"::1" |
true |
false |
"2001::1" |
true |
false |
"1::" |
true |
false |
"1:2:3:4:5:6:7:8" |
true |
true (uncompressed form — only form that works) |
A secondary bug: the final check groups >= 1 on line 243 rejects "::" (the valid all-zeros address per RFC 4291 — :: is the shortened form of the all-zeros IPv6 address), even if the loop were fixed.
compression_used (Line 214) is also set but never read — dead variable.
The simplest correct fix is to advance pos past both colons of :: when compression is detected, and change the lower bound of groups to 0:
🛠️ Proposed fix for the `::` double-colon parsing logic
int groups = 0;
size_t pos = 0;
- bool compression_used = false;
while (pos <= address.size()) {
size_t next = address.find(':', pos);
if (next == std::string::npos) {
next = address.size();
}
size_t len = next - pos;
if (len > 0) {
if (len > 4) {
return false;
}
++groups;
} else {
if (has_double_colon && pos == double_colon) {
- compression_used = true;
+ // Skip over the second ':' of "::" so the next iteration
+ // does not see another spurious zero-length segment.
+ if (next == address.size()) {
+ break;
+ }
+ pos = next + 2; // jump past both colons
+ continue;
} else if (pos > 0 && next < address.size()) {
return false;
}
}
if (next == address.size()) {
break;
}
pos = next + 1;
}
if (has_double_colon) {
- return groups >= 1 && groups <= 7;
+ return groups >= 0 && groups <= 7; // "::" alone is valid (0 explicit groups)
}
return groups == 8;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/transport/endpoint.cpp` around lines 216 - 245, The IPv6
compressed-address parsing incorrectly treats the two zero-length segments from
"::" as an error; in the loop that scans segments (using pos, next, len,
double_colon, groups) detect the compression branch when len == 0 and pos ==
double_colon and advance pos past both colons (i.e., skip the adjacent empty
segment so the next iteration doesn't immediately fail), instead of only
accepting the first empty segment; also change the final validation for
compression (the has_double_colon branch) to allow groups >= 0 (so "::" is
valid), and remove or stop using the dead variable compression_used (or
repurpose it if needed). Ensure these changes are applied around the while loop
and the final groups check in the function that validates IPv6 addresses.
| CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" | ||
| CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify where sample IPv4 endpoint addresses are defined.
rg -n 'CONFIG_NET_CONFIG_(MY|PEER)_IPV4_ADDR' zephyr/samples/net_testRepository: vtz/opensomeip
Length of output: 217
🏁 Script executed:
#!/bin/bash
# Explore the directory structure of net_test sample
ls -la zephyr/samples/net_test/Repository: vtz/opensomeip
Length of output: 338
🏁 Script executed:
#!/bin/bash
# Check for overlay files in the net_test sample
find zephyr/samples/net_test -type f -name "*.overlay" -o -name "*overlay*" | head -20Repository: vtz/opensomeip
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Check prj.conf content to see the full context
cat -n zephyr/samples/net_test/prj.conf | head -30Repository: vtz/opensomeip
Length of output: 888
🏁 Script executed:
#!/bin/bash
# Search for .overlay files in the samples directory
find zephyr/samples -name "*.overlay" -type f | head -20Repository: vtz/opensomeip
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Check if other net samples use overlays or hardcoded addresses
find zephyr/samples -name "prj.conf" -type f -exec grep -l 'CONFIG_NET_CONFIG.*IPV4_ADDR' {} \;Repository: vtz/opensomeip
Length of output: 126
🏁 Script executed:
#!/bin/bash
# Look at another net sample structure for comparison
ls -la zephyr/samples/ | grep -E "^d" | head -10Repository: vtz/opensomeip
Length of output: 523
🏁 Script executed:
#!/bin/bash
# Check someip_echo config for consistency
cat -n zephyr/samples/someip_echo/prj.conf | grep -i ipv4Repository: vtz/opensomeip
Length of output: 221
🏁 Script executed:
#!/bin/bash
# Check the root structure to understand project context
ls -la | head -20
cat README.md 2>/dev/null | head -30Repository: vtz/opensomeip
Length of output: 2821
Hardcoded IPv4 addresses limit test configuration flexibility.
Lines 14-15 hardcode endpoint addresses (192.0.2.1, 192.0.2.2) in the base configuration, preventing easy reconfiguration for different topologies in parallel test/simulation environments. Consider moving these to a flexible configuration mechanism (board overlays, environment variables, or CMake-based configuration) to allow dynamic address assignment per test scenario.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/samples/net_test/prj.conf` around lines 14 - 15, The config currently
hardcodes endpoint IPs via CONFIG_NET_CONFIG_MY_IPV4_ADDR and
CONFIG_NET_CONFIG_PEER_IPV4_ADDR; replace this by making the addresses
configurable at build/run time — remove the fixed literals from prj.conf and
instead expose these as build-time variables (e.g., set defaults in Kconfig or
leave unset and inject values via board overlays, CMake -D options, or
environment-backed config fragments) so each test/simulation can supply distinct
IPv4 addresses per scenario using the board overlay names or CMake variable
names that map to CONFIG_NET_CONFIG_MY_IPV4_ADDR and
CONFIG_NET_CONFIG_PEER_IPV4_ADDR.
| SessionManager sm; | ||
| uint16_t s1 = sm.get_next_session_id(); | ||
| uint16_t s2 = sm.get_next_session_id(); | ||
| CHECK(s2 == s1 + 1, "sequential_ids"); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Nit: guard sequential-ID check against uint16_t wraparound.
s1 + 1 promotes to int; if a future SessionManager implementation starts or wraps at 0xFFFF, s2 wraps to 0 while s1 + 1 stays 65536, silently failing the assertion. A cast makes the intent explicit and wraparound-safe.
🛠️ Proposed fix
- CHECK(s2 == s1 + 1, "sequential_ids");
+ CHECK(s2 == static_cast<uint16_t>(s1 + 1u), "sequential_ids");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CHECK(s2 == s1 + 1, "sequential_ids"); | |
| CHECK(s2 == static_cast<uint16_t>(s1 + 1u), "sequential_ids"); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@zephyr/tests/test_core/src/main.cpp` at line 94, The sequential-ID assertion
can fail on uint16_t wraparound; change the comparison to perform the increment
in the same uint16_t domain so wraparound is handled, e.g. compare s2 against
static_cast<uint16_t>(s1 + 1) (or
static_cast<uint16_t>(static_cast<uint16_t>(s1) + 1)) inside the CHECK call that
uses s1, s2 and the "sequential_ids" tag so the intent is explicit and safe if
IDs wrap at 0xFFFF.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
src/transport/endpoint.cpp (1)
229-243:⚠️ Potential issue | 🔴 CriticalIPv6
::compression handling still rejects valid addresses (e.g.,2001::1,1::).The empty-group logic around Line 230-234 still fails for non-leading compression positions, causing valid compressed IPv6 addresses to be rejected.
🛠️ Focused fix
- } else { - // Allow a single "::" compression sequence (two adjacent colons). - if (has_double_colon && !compression_used && pos == double_colon) { - compression_used = true; - } else if (has_double_colon && compression_used && pos == double_colon + 1) { - // Second ':' from the same "::" token; valid, nothing to count. - } else if (pos > 0 && next < address.size()) { - return false; - } - } + } else { + // Handle "::" once, regardless of whether parser is at first or second ':' + // (e.g., "::1", "2001::1", "1::"). + if (has_double_colon && !compression_used && + (pos == double_colon || pos == double_colon + 1)) { + compression_used = true; + pos = double_colon + 2; // first char after "::" + if (pos > address.size()) { + break; + } + continue; + } else if (pos > 0 && next < address.size()) { + return false; + } + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/transport/endpoint.cpp` around lines 229 - 243, The parser currently treats an empty group (next == pos) as invalid unless at the start, which rejects valid compressed IPv6 addresses; update the empty-group branch in the loop that uses has_double_colon, compression_used, pos and double_colon so that when next == pos and has_double_colon and pos == double_colon and !compression_used you set compression_used = true and continue (do not fall through to the failure case), and preserve the existing special-case for the second ':' (pos == double_colon + 1); this ensures a single "::" is accepted wherever double_colon appears (e.g., in 2001::1 or 1::) without changing other validation paths..github/workflows/zephyr.yml (2)
2-2:⚠️ Potential issue | 🟡 MinorYAMLlint formatting issues are still present in flow maps and the
onkey.Static analysis flags Line [2] (
truthy) and brace-spacing errors at Lines [25], [41], [47], [53], [63], [69], [87]. Normalize these to avoid lint failures.🧹 Suggested normalization
-on: +'on': @@ - container: { image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4" } + container: {image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4"} @@ - env: { ZEPHYR_BASE: /tmp/zp/zephyr } + env: {ZEPHYR_BASE: /tmp/zp/zephyr} @@ - env: { ZEPHYR_BASE: /tmp/zp/zephyr } + env: {ZEPHYR_BASE: /tmp/zp/zephyr} @@ - env: { ZEPHYR_BASE: /tmp/zp/zephyr } + env: {ZEPHYR_BASE: /tmp/zp/zephyr} @@ - env: { ZEPHYR_BASE: /tmp/zp/zephyr } + env: {ZEPHYR_BASE: /tmp/zp/zephyr} @@ - container: { image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4" } + container: {image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4"} @@ - env: { ZEPHYR_BASE: /tmp/zp/zephyr } + env: {ZEPHYR_BASE: /tmp/zp/zephyr}Also applies to: 25-25, 41-41, 47-47, 53-53, 63-63, 69-69, 87-87
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml at line 2, YAML lint failures stem from using flow-map syntax and inconsistent brace/space placement around the top-level on key and several inline maps; update the workflow to use block-style mappings for the on key and any flow maps (replace {key: value} with multiline key: value blocks) and normalize spacing around braces/brackets (ensure a single space after commas and no extra spaces inside braces) for the affected flow-map entries so the file passes yamllint; target the top-level "on" mapping and the inline flow maps currently present (the flow-map entries flagged by the linter) and re-run yamllint to verify.
30-34:⚠️ Potential issue | 🟠 MajorAdd checksum verification before extracting SDK/toolchain archives.
Lines [32], [76]-[77] download release tarballs and Lines [33], [78]-[79] extract them without integrity checks. That is a supply-chain gap in CI.
🔐 Suggested hardening
zephyr-native-sim: @@ env: ZEPHYR_SDK_INSTALL_DIR: /opt/zephyr-sdk-0.17.0 + ZEPHYR_SDK_MINIMAL_SHA256: "<pin-official-sha256>" @@ - name: Install Zephyr SDK run: | wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz + echo "${ZEPHYR_SDK_MINIMAL_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ /opt/zephyr-sdk-0.17.0/setup.sh -c zephyr-s32k344-build: @@ env: ZEPHYR_SDK_INSTALL_DIR: /opt/zephyr-sdk-0.17.0 + ZEPHYR_SDK_MINIMAL_SHA256: "<pin-official-sha256>" + ZEPHYR_ARM_TOOLCHAIN_SHA256: "<pin-official-sha256>" @@ - name: Install Zephyr SDK run: | wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz + echo "${ZEPHYR_SDK_MINIMAL_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - + echo "${ZEPHYR_ARM_TOOLCHAIN_SHA256} toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz" | sha256sum -c - tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ tar xf toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz -C /opt/zephyr-sdk-0.17.0/ /opt/zephyr-sdk-0.17.0/setup.sh -cAlso applies to: 74-80
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 30 - 34, The workflow downloads and extracts SDK tarballs (the "Install Zephyr SDK" run block invoking wget for zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz and then tar xf) without verifying integrity; add checksum verification between the download and extraction: fetch the upstream checksum file or store the expected sha256 in repo, compute the downloaded file's sha256 and compare (or use sha256sum -c) and exit non‑zero on mismatch, then only run tar xf on successful verification; apply the same pattern to the other download/extract blocks referenced around lines 76-80 so all releases are verified before extraction.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/zephyr.yml:
- Around line 58-61: The timeout command's exit code is not captured because
bash -e causes the step to exit early; wrap the call to timeout 30
build/ns_echo/zephyr/zephyr.exe with a temporary disable of errexit so rc gets
set (e.g. set +e; timeout 30 build/ns_echo/zephyr/zephyr.exe; rc=$?; set -e) and
then keep the existing if [ "$rc" -ne 0 ] && [ "$rc" -ne 124 ]; then exit "$rc";
fi check, ensuring you reference the timeout invocation and the rc variable so
the conditional can work as intended.
---
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Line 2: YAML lint failures stem from using flow-map syntax and inconsistent
brace/space placement around the top-level on key and several inline maps;
update the workflow to use block-style mappings for the on key and any flow maps
(replace {key: value} with multiline key: value blocks) and normalize spacing
around braces/brackets (ensure a single space after commas and no extra spaces
inside braces) for the affected flow-map entries so the file passes yamllint;
target the top-level "on" mapping and the inline flow maps currently present
(the flow-map entries flagged by the linter) and re-run yamllint to verify.
- Around line 30-34: The workflow downloads and extracts SDK tarballs (the
"Install Zephyr SDK" run block invoking wget for
zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz and then tar xf) without verifying
integrity; add checksum verification between the download and extraction: fetch
the upstream checksum file or store the expected sha256 in repo, compute the
downloaded file's sha256 and compare (or use sha256sum -c) and exit non‑zero on
mismatch, then only run tar xf on successful verification; apply the same
pattern to the other download/extract blocks referenced around lines 76-80 so
all releases are verified before extraction.
In `@src/transport/endpoint.cpp`:
- Around line 229-243: The parser currently treats an empty group (next == pos)
as invalid unless at the start, which rejects valid compressed IPv6 addresses;
update the empty-group branch in the loop that uses has_double_colon,
compression_used, pos and double_colon so that when next == pos and
has_double_colon and pos == double_colon and !compression_used you set
compression_used = true and continue (do not fall through to the failure case),
and preserve the existing special-case for the second ':' (pos == double_colon +
1); this ensures a single "::" is accepted wherever double_colon appears (e.g.,
in 2001::1 or 1::) without changing other validation paths.
There was a problem hiding this comment.
♻️ Duplicate comments (3)
.github/workflows/zephyr.yml (3)
30-34:⚠️ Potential issue | 🟠 MajorDownloaded SDK/toolchain archives are extracted without integrity checks.
At Line 32, Line 87, and Line 88, tarballs are downloaded and extracted before any checksum validation. This is a supply-chain risk in CI.
🔒 Suggested hardening
- name: Install Zephyr SDK + env: + ZEPHYR_SDK_MIN_SHA256: "<official_sha256_for_zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz>" run: | wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz + echo "${ZEPHYR_SDK_MIN_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ /opt/zephyr-sdk-0.17.0/setup.sh -c @@ - name: Install Zephyr SDK + env: + ZEPHYR_SDK_MIN_SHA256: "<official_sha256_for_zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz>" + ZEPHYR_ARM_TC_SHA256: "<official_sha256_for_toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz>" run: | wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz + echo "${ZEPHYR_SDK_MIN_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - + echo "${ZEPHYR_ARM_TC_SHA256} toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz" | sha256sum -c - tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ tar xf toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz -C /opt/zephyr-sdk-0.17.0/ /opt/zephyr-sdk-0.17.0/setup.sh -c#!/bin/bash # Read-only check that every SDK/toolchain download is paired with checksum validation. set -euo pipefail rg -n 'wget .*sdk-ng/releases/download/v0\.17\.0' .github/workflows/zephyr.yml rg -n 'sha256sum -c|shasum -a 256' .github/workflows/zephyr.ymlAlso applies to: 87-91
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 30 - 34, The workflow currently downloads and extracts Zephyr SDK archives in the "Install Zephyr SDK" step (wget + tar + /opt/zephyr-sdk-0.17.0/setup.sh) without integrity verification; update that step (and the similar download/extract steps around lines referenced) to fetch the corresponding checksum (or signature) file for zephyr-sdk-0.17.0 and verify the archive before extraction using a tool like sha256sum -c or gpg --verify, fail the job if verification fails, and only run tar xf and setup.sh after the checksum/signature check succeeds so the downloaded tarball is validated prior to extraction.
2-2:⚠️ Potential issue | 🟡 MinorCurrent YAML still violates the reported yamllint rules.
Line 2 (
on:truthy key) and flow-map spacing at Line 25/41/53/64/74/80/98 match current static-analysis findings. If yamllint is enforced, this can fail CI.#!/bin/bash # Reproduce lint signals for this workflow file. set -euo pipefail python3 -m pip install --quiet yamllint==1.38.0 yamllint .github/workflows/zephyr.ymlAlso applies to: 25-25, 41-41, 53-53, 64-64, 74-74, 80-80, 98-98
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml at line 2, The workflow YAML currently violates yamllint: replace the bare truthy key "on:" with an explicit value (for example use "on: {}", or a proper event mapping like "on: push" or "on: [push]") to satisfy the truthy-key rule, and fix all inline flow-maps so they have proper spacing around colons and commas (change occurrences of "{key:value,foo:bar}" to "{key: value, foo: bar}" wherever inline mappings are used). Ensure you update the "on" key and every inline flow-map instance in the file to match yamllint spacing rules.
46-50:⚠️ Potential issue | 🔴 CriticalTimeout exit-code handling is brittle and can bypass intended logic.
At Line 46, Line 57, and Line 69, failure handling depends on shell behavior that is inconsistent here (
PIPESTATUSis bash-specific, and-ecan exit beforercchecks). This can make timeout acceptance logic unreliable.✅ Suggested fix
zephyr-native-sim: name: Zephyr native_sim runs-on: ubuntu-latest container: { image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4" } + defaults: + run: + shell: bash @@ - name: Build & run test_core env: { ZEPHYR_BASE: /tmp/zp/zephyr } run: | west build -b native_sim zephyr/tests/test_core -d build/ns_tc --pristine auto @@ - timeout 30 build/ns_tc/zephyr/zephyr.exe | tee /tmp/test_core.log; rc=${PIPESTATUS[0]} + set +e + timeout 30 build/ns_tc/zephyr/zephyr.exe | tee /tmp/test_core.log + rc=${PIPESTATUS[0]} + set -e @@ - name: Build & run test_transport env: { ZEPHYR_BASE: /tmp/zp/zephyr } run: | west build -b native_sim zephyr/tests/test_transport -d build/ns_tp --pristine auto @@ - timeout 30 build/ns_tp/zephyr/zephyr.exe | tee /tmp/test_transport.log; rc=${PIPESTATUS[0]} + set +e + timeout 30 build/ns_tp/zephyr/zephyr.exe | tee /tmp/test_transport.log + rc=${PIPESTATUS[0]} + set -e @@ - name: Build & run someip_echo env: { ZEPHYR_BASE: /tmp/zp/zephyr } run: | west build -b native_sim zephyr/samples/someip_echo -d build/ns_echo --pristine auto @@ - timeout 30 build/ns_echo/zephyr/zephyr.exe; rc=$? + rc=0 + timeout 30 build/ns_echo/zephyr/zephyr.exe || rc=$? if [ "$rc" -ne 0 ] && [ "$rc" -ne 124 ]; then exit "$rc" fi#!/bin/bash # Verify shell-sensitive patterns in the workflow (read-only). set -euo pipefail rg -n 'PIPESTATUS|timeout 30 .*; rc=\$\?|defaults:\s*$|shell:\s*bash' .github/workflows/zephyr.yml sed -n '35,75p' .github/workflows/zephyr.ymlAlso applies to: 57-61, 69-71
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 30-34: The workflow currently downloads and extracts Zephyr SDK
archives in the "Install Zephyr SDK" step (wget + tar +
/opt/zephyr-sdk-0.17.0/setup.sh) without integrity verification; update that
step (and the similar download/extract steps around lines referenced) to fetch
the corresponding checksum (or signature) file for zephyr-sdk-0.17.0 and verify
the archive before extraction using a tool like sha256sum -c or gpg --verify,
fail the job if verification fails, and only run tar xf and setup.sh after the
checksum/signature check succeeds so the downloaded tarball is validated prior
to extraction.
- Line 2: The workflow YAML currently violates yamllint: replace the bare truthy
key "on:" with an explicit value (for example use "on: {}", or a proper event
mapping like "on: push" or "on: [push]") to satisfy the truthy-key rule, and fix
all inline flow-maps so they have proper spacing around colons and commas
(change occurrences of "{key:value,foo:bar}" to "{key: value, foo: bar}"
wherever inline mappings are used). Ensure you update the "on" key and every
inline flow-map instance in the file to match yamllint spacing rules.
There was a problem hiding this comment.
♻️ Duplicate comments (3)
.github/workflows/zephyr.yml (3)
32-33:⚠️ Potential issue | 🟠 MajorSDK/toolchain archives are extracted without integrity verification.
Lines 32-33 and 89-92 untar downloaded artifacts before checksum validation, which is a supply-chain risk.
🔐 Hardening diff
- name: Install Zephyr SDK run: | wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz + echo "${ZEPHYR_SDK_MINIMAL_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ @@ - name: Install Zephyr SDK run: | wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz + echo "${ZEPHYR_SDK_MINIMAL_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - + echo "${ZEPHYR_TOOLCHAIN_ARM_SHA256} toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz" | sha256sum -c - tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ tar xf toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz -C /opt/zephyr-sdk-0.17.0/Also applies to: 89-92
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 32 - 33, The workflow untars SDK artifacts immediately after wget (the zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz download step and the analogous download at the second occurrence) without verifying integrity; change the steps around the wget + tar invocations to also fetch the provider's SHA256 (or .sha256) checksum for the same release, compute the archive's checksum (e.g., with sha256sum) and verify it matches (failing the job on mismatch) before running tar xf; ensure the same verification is added for both occurrences (the zephyr-sdk download block and the second artifact block) and that the job exits nonzero when verification fails.
2-8:⚠️ Potential issue | 🟡 MinorYAML lint violations remain for
onkey and flow-map spacing.Line 2 (
on:) still triggers YAML truthy warning, and inline maps likeenv: { ZEPHYR_BASE: ... }still trigger brace-spacing errors. If yamllint is enforced, this will keep failing CI.🧹 Suggested normalization
-on: +'on': @@ - container: { image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4" } + container: {image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4"} @@ - env: { ZEPHYR_BASE: /tmp/zp/zephyr } + env: {ZEPHYR_BASE: /tmp/zp/zephyr}Apply the same map-spacing normalization consistently at Lines 54, 66, 76, 82, and 100.
Also applies to: 25-25, 41-41, 54-54, 66-66, 76-76, 82-82, 100-100
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 2 - 8, Quote the top-level on key (e.g., change on: to 'on':) to satisfy yamllint truthy-key rules and replace any inline flow-maps like env: { ZEPHYR_BASE: ... } with equivalent block mappings (env: and then a newline list of KEY: VALUE entries) to fix brace/flow-map spacing; apply this normalization consistently for all occurrences (the push and pull_request blocks and every env/inline map instance referenced in the PR) so yamllint no longer reports truthy/on key or flow-map spacing violations.
46-52:⚠️ Potential issue | 🟠 Major
timeoutexit code handling is still fragile under-eshells.At Lines 46, 58, and 71,
timeout ...; rc=$?can skiprcassignment whentimeoutreturns non-zero (including124), so the fallback logic may never run.✅ Safer pattern (works with errexit)
- timeout 30 build/ns_tc/zephyr/zephyr.exe > /tmp/test_core.log 2>&1; rc=$? + rc=0 + timeout 30 build/ns_tc/zephyr/zephyr.exe > /tmp/test_core.log 2>&1 || rc=$? @@ - timeout 30 build/ns_tp/zephyr/zephyr.exe > /tmp/test_transport.log 2>&1; rc=$? + rc=0 + timeout 30 build/ns_tp/zephyr/zephyr.exe > /tmp/test_transport.log 2>&1 || rc=$? @@ - timeout 30 build/ns_echo/zephyr/zephyr.exe; rc=$? + rc=0 + timeout 30 build/ns_echo/zephyr/zephyr.exe || rc=$?#!/bin/bash # Verify risky pattern still exists in workflow: rg -n 'timeout 30 .*; rc=\$\?' .github/workflows/zephyr.yml # Reproduce behavior under errexit: sh -ec 'timeout 0.1 sleep 1; rc=$?; echo "rc=$rc"' || echo "rc assignment skipped under -e" # Validate safe pattern: sh -ec 'rc=0; timeout 0.1 sleep 1 || rc=$?; echo "rc=$rc"'Also applies to: 58-64, 71-74
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 46 - 52, The timeout command's exit code assignment uses a fragile pattern "timeout ...; rc=$?" which can be skipped under shells with errexit (-e); replace each occurrence (e.g., the "timeout 30 build/ns_tc/zephyr/zephyr.exe > /tmp/test_core.log 2>&1; rc=$?" line and the similar invocations at the other locations) with a safe pattern that guarantees rc is set even if timeout fails, for example run timeout ... || rc=$? (or pre-set rc=0; timeout ... || rc=$?) so the subsequent conditional logic that checks rc (for 124 or non-zero) always executes reliably. Ensure you update all three occurrences mentioned in the review.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 32-33: The workflow untars SDK artifacts immediately after wget
(the zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz download step and the
analogous download at the second occurrence) without verifying integrity; change
the steps around the wget + tar invocations to also fetch the provider's SHA256
(or .sha256) checksum for the same release, compute the archive's checksum
(e.g., with sha256sum) and verify it matches (failing the job on mismatch)
before running tar xf; ensure the same verification is added for both
occurrences (the zephyr-sdk download block and the second artifact block) and
that the job exits nonzero when verification fails.
- Around line 2-8: Quote the top-level on key (e.g., change on: to 'on':) to
satisfy yamllint truthy-key rules and replace any inline flow-maps like env: {
ZEPHYR_BASE: ... } with equivalent block mappings (env: and then a newline list
of KEY: VALUE entries) to fix brace/flow-map spacing; apply this normalization
consistently for all occurrences (the push and pull_request blocks and every
env/inline map instance referenced in the PR) so yamllint no longer reports
truthy/on key or flow-map spacing violations.
- Around line 46-52: The timeout command's exit code assignment uses a fragile
pattern "timeout ...; rc=$?" which can be skipped under shells with errexit
(-e); replace each occurrence (e.g., the "timeout 30
build/ns_tc/zephyr/zephyr.exe > /tmp/test_core.log 2>&1; rc=$?" line and the
similar invocations at the other locations) with a safe pattern that guarantees
rc is set even if timeout fails, for example run timeout ... || rc=$? (or
pre-set rc=0; timeout ... || rc=$?) so the subsequent conditional logic that
checks rc (for 124 or non-zero) always executes reliably. Ensure you update all
three occurrences mentioned in the review.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
.github/workflows/zephyr.yml (2)
32-34:⚠️ Potential issue | 🟠 MajorVerify downloaded SDK/toolchain archives before extraction.
Lines 32–34 and 101–105 download and extract archives without integrity checks. This is a supply-chain risk and should fail fast on checksum mismatch.
✅ Suggested hardening
+ - name: Install Zephyr SDK + env: + ZEPHYR_SDK_MINIMAL_SHA256: "<expected_sha256>" + ZEPHYR_TOOLCHAIN_ARM_SHA256: "<expected_sha256>" + run: | + wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz + echo "${ZEPHYR_SDK_MINIMAL_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - + tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ + /opt/zephyr-sdk-0.17.0/setup.sh -c- name: Install Zephyr SDK run: | wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.0/toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz + echo "${ZEPHYR_SDK_MINIMAL_SHA256} zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz" | sha256sum -c - + echo "${ZEPHYR_TOOLCHAIN_ARM_SHA256} toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz" | sha256sum -c - tar xf zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz -C /opt/ tar xf toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz -C /opt/zephyr-sdk-0.17.0/ /opt/zephyr-sdk-0.17.0/setup.sh -cAlso applies to: 101-105
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml around lines 32 - 34, The wget + tar extraction steps currently run without integrity checks; update both download-extract blocks that use the zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz and any other archive (the wget/tar + /opt/zephyr-sdk-0.17.0/setup.sh sequence) to verify the archive checksum before extraction: download or embed the expected SHA256 checksum, compute the downloaded file's sha256sum and validate it (failing fast on mismatch), and only then run tar and setup.sh; ensure the script returns a non-zero exit on verification failure and cleans up the bad download.
25-25:⚠️ Potential issue | 🟡 MinorNormalize inline map spacing to satisfy YAMLlint brace rules.
YAMLlint reports brace-spacing errors on these lines (
{ key: value }). Normalize spacing (or switch to block style) to avoid lint failures.🧹 Suggested normalization
- container: { image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4" } + container: {image: "ghcr.io/zephyrproject-rtos/ci:v0.27.4"} ... - env: { ZEPHYR_BASE: /tmp/zp/zephyr } + env: {ZEPHYR_BASE: /tmp/zp/zephyr}Also applies to: 41-41, 58-58, 74-74, 88-88, 94-94, 112-112
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/zephyr.yml at line 25, Normalize each inline mapping used with the container key and similar entries by ensuring a single space after the opening brace, a single space before the closing brace, and a single space after the colon (e.g., change any "{image:...}" or "{ image:...}" to "{ image: \"...\" }"), or convert the inline map to block style; update the occurrences referenced (the container mapping and the other inline maps at the same pattern) so they consistently follow the brace-spacing rule to satisfy YAMLlint.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/zephyr.yml:
- Around line 1-10: Add a top-level permissions block to this "Zephyr Build &
Test" workflow to enforce least-privilege for GITHUB_TOKEN by specifying only
the read scopes needed for checkout/build (e.g., add permissions: contents: read
at workflow scope). Update the workflow YAML to include the permissions key
before jobs so the token has minimal access during the run.
- Around line 38-39: The workflow uses "west init /tmp/zp" without pinning to a
specific Zephyr revision; change both invocations of west init (the command
occurrences in the file) to include --mr=<fixed-commit-or-tag> (e.g.,
--mr=refs/tags/<tag> or --mr=<commit-hash>) so the CI initializes Zephyr at a
reproducible revision; update both places where "west init /tmp/zp" appears
(lines referenced in the review) to use the same chosen --mr value.
---
Duplicate comments:
In @.github/workflows/zephyr.yml:
- Around line 32-34: The wget + tar extraction steps currently run without
integrity checks; update both download-extract blocks that use the
zephyr-sdk-0.17.0_linux-x86_64_minimal.tar.xz and any other archive (the
wget/tar + /opt/zephyr-sdk-0.17.0/setup.sh sequence) to verify the archive
checksum before extraction: download or embed the expected SHA256 checksum,
compute the downloaded file's sha256sum and validate it (failing fast on
mismatch), and only then run tar and setup.sh; ensure the script returns a
non-zero exit on verification failure and cleans up the bad download.
- Line 25: Normalize each inline mapping used with the container key and similar
entries by ensuring a single space after the opening brace, a single space
before the closing brace, and a single space after the colon (e.g., change any
"{image:...}" or "{ image:...}" to "{ image: \"...\" }"), or convert the inline
map to block style; update the occurrences referenced (the container mapping and
the other inline maps at the same pattern) so they consistently follow the
brace-spacing rule to satisfy YAMLlint.
| name: Zephyr Build & Test | ||
| on: | ||
| push: | ||
| branches: ["main","feature/zephyr-port"] | ||
| paths-ignore: ['**/*.md','docs/**','LICENSE','.cursor/**'] | ||
| pull_request: | ||
| branches: ["main"] | ||
| paths-ignore: ['**/*.md','docs/**','LICENSE','.cursor/**'] | ||
|
|
||
| jobs: |
There was a problem hiding this comment.
Set least-privilege workflow token permissions explicitly.
There is no permissions: block at workflow scope, so GITHUB_TOKEN may be broader than necessary. This workflow only needs read access for checkout/build.
🔒 Suggested minimal permissions
name: Zephyr Build & Test
on:
@@
+permissions:
+ contents: read
+
jobs:🧰 Tools
🪛 YAMLlint (1.38.0)
[warning] 2-2: truthy value should be one of [false, true]
(truthy)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/zephyr.yml around lines 1 - 10, Add a top-level
permissions block to this "Zephyr Build & Test" workflow to enforce
least-privilege for GITHUB_TOKEN by specifying only the read scopes needed for
checkout/build (e.g., add permissions: contents: read at workflow scope). Update
the workflow YAML to include the permissions key before jobs so the token has
minimal access during the run.
| west init /tmp/zp && cd /tmp/zp | ||
| west update --narrow -o=--depth=1 && west zephyr-export |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify all west init invocations and whether they pin a revision.
rg -nP --type=yaml '\bwest init\b' .github/workflows -C2
echo "---- pinned with --mr ----"
rg -nP --type=yaml '\bwest init\b.*\b--mr\b' .github/workflows -C2 || trueRepository: vtz/opensomeip
Length of output: 805
Pin west init to a fixed Zephyr revision.
Lines 38 and 109 use west init /tmp/zp without --mr, causing CI to track whatever upstream default branch points to at runtime. This makes builds non-reproducible and prone to sudden breakage.
Suggested change
+ env:
+ ZEPHYR_REVISION: "<tested_tag_or_commit>"
...
- west init /tmp/zp && cd /tmp/zp
+ west init --mr "$ZEPHYR_REVISION" /tmp/zp && cd /tmp/zp
west update --narrow -o=--depth=1 && west zephyr-exportApply this fix to both invocations at lines 38 and 109.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/zephyr.yml around lines 38 - 39, The workflow uses "west
init /tmp/zp" without pinning to a specific Zephyr revision; change both
invocations of west init (the command occurrences in the file) to include
--mr=<fixed-commit-or-tag> (e.g., --mr=refs/tags/<tag> or --mr=<commit-hash>) so
the CI initializes Zephyr at a reproducible revision; update both places where
"west init /tmp/zp" appears (lines referenced in the review) to use the same
chosen --mr value.
Summary by CodeRabbit
New Features
Tests
Chores
Documentation