RDKEMW-21185: Add exitcode on container stopped event - #465
Conversation
goruklu
left a comment
There was a problem hiding this comment.
the changes look good but it's missing L1 & L2 unit tests. Please add them
There was a problem hiding this comment.
Pull request overview
Adds support for surfacing a container’s exit code on stop events through a new “stopped-with-status” signal pathway, updating the client proxy API and adding unit/integration tests to validate exit-code extraction and listener dispatch behavior.
Changes:
- Extend
IDobbyProxy/DobbyProxywithregisterListenerWithStatus/unregisterListenerWithStatusand aStoppedWithStatussignal handler that extracts exit code fromwaitpidstatus. - Add L1 unit tests for the new listener lifecycle, argument parsing, and dispatch isolation between
StoppedvsStoppedWithStatus. - Add L2 integration tests + a new container spec to validate
StoppedWithStatusemission and correct exit code encoding.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/L2_testing/test_runner/runner.py | Registers the new L2 exit-code test group in the runner. |
| tests/L2_testing/test_runner/exit_code_tests.py | New L2 tests that monitor D-Bus signals and verify exit code extraction. |
| tests/L2_testing/dobby_specs/exit_with_code.json | New container spec that exits with code 42 for L2 validation. |
| tests/L1_testing/tests/DobbyProxyTest/DobbyProxyTests.cpp | New L1 tests covering status listener API and exit code parsing/dispatch. |
| tests/L1_testing/tests/DobbyProxyTest/CMakeLists.txt | New build target for the DobbyProxy L1 tests. |
| tests/L1_testing/tests/CMakeLists.txt | Adds the new DobbyProxyTest subdirectory to the L1 test build. |
| client/lib/source/DobbyProxy.cpp | Subscribes to new stop-with-status signal, parses raw status, dispatches to status listeners. |
| client/lib/include/DobbyProxy.h | Extends proxy interface and state-change event structure to include exit code and new listener set. |
| AppInfrastructure/Public/Dobby/IDobbyProxy.h | Public API additions for status listeners that receive an exit code. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (7)
client/lib/source/DobbyProxy.cpp:105
- The registration token for the STARTED signal (mContainerStartedSignal) is overwritten when registering the HIBERNATED signal, which means: (1) failures registering STARTED can be masked, and (2) the STARTED handler cannot be unregistered in the destructor (potential use-after-free if the IPC layer delivers signals after the object is destroyed). Store distinct registration IDs for each signal (Started/Hibernated/Awoken) and unregister them all in ~DobbyProxy().
const AI_IPC::Signal hibernatedSignal(objectName, DOBBY_CTRL_INTERFACE, DOBBY_CTRL_EVENT_HIBERNATED);
const AI_IPC::SignalHandler hibernatedHandler(std::bind(&DobbyProxy::onContainerHibernatedEvent, this, std::placeholders::_1));
mContainerStartedSignal = mIpcService->registerSignalHandler(hibernatedSignal, hibernatedHandler);
client/lib/source/DobbyProxy.cpp:111
- mContainerStartedSignal is overwritten again when registering the AWOKEN signal, leaving the STARTED (and HIBERNATED) registration IDs lost and not unregistered. This can also make the constructor’s empty-check validate the wrong token.
const AI_IPC::Signal awokenSignal(objectName, DOBBY_CTRL_INTERFACE, DOBBY_CTRL_EVENT_AWOKEN);
const AI_IPC::SignalHandler awokenHandler(std::bind(&DobbyProxy::onContainerAwokenEvent, this, std::placeholders::_1));
mContainerStartedSignal = mIpcService->registerSignalHandler(awokenSignal, awokenHandler);
if (mContainerStartedSignal.empty() || mContainerStoppedSignal.empty() || mContainerStoppedWithStatusSignal.empty())
tests/L2_testing/test_runner/exit_code_tests.py:41
- sleep and basename are imported but unused. Removing them avoids unused-import warnings and keeps dependencies minimal.
from time import sleep, monotonic
from os.path import basename
tests/L1_testing/tests/DobbyProxyTest/CMakeLists.txt:48
- IpcVariantList.cpp is compiled into DobbyProxyTestLib (add_library ...) and also added to the test executable sources via file(GLOB ... ../../mocks/IpcVariantList.cpp). This will typically cause duplicate symbol / multiple definition link errors. Remove it from the executable sources (or remove it from the static lib and keep it only in the executable).
file(GLOB TESTS *.cpp
../../mocks/IpcVariantList.cpp
)
tests/L2_testing/test_runner/exit_code_tests.py:109
- DbusSignalCapture starts dbus-monitor with stderr=PIPE but never consumes it. If dbus-monitor writes enough to stderr (warnings/errors), it can block on a full pipe and cause the test to hang. Redirect stderr to STDOUT or DEVNULL.
["dbus-monitor", "--system", match_rule],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
tests/L2_testing/test_runner/exit_code_tests.py:39
- Several imports are unused (os, sys, select). Keeping unused imports makes the file noisier and can fail linting if enabled for the test runner.
This issue also appears on line 40 of the same file.
import os
import sys
import threading
import select
import re
tests/L2_testing/test_runner/exit_code_tests.py:160
- The docstring says this returns a list of (descriptor, name, raw_status) tuples, but the function actually appends dict objects. Update the docstring (or the return type) so callers aren’t misled.
Returns a list of (descriptor, name, raw_status) tuples for each match.
"""
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (3)
client/lib/source/DobbyProxy.cpp:109
mContainerStartedSignalis overwritten with the registration IDs for the Hibernated and Awoken signals. This loses the original Started registration ID, breaks the emptiness check (it no longer reflects Started), and means the destructor will only unregister the last assigned handler (leaving the others registered). Each signal registration needs its own member (or otherwise retained) registration ID so they can all be validated and unregistered correctly.
mContainerStartedSignal = mIpcService->registerSignalHandler(hibernatedSignal, hibernatedHandler);
const AI_IPC::Signal awokenSignal(objectName, DOBBY_CTRL_INTERFACE, DOBBY_CTRL_EVENT_AWOKEN);
const AI_IPC::SignalHandler awokenHandler(std::bind(&DobbyProxy::onContainerAwokenEvent, this, std::placeholders::_1));
mContainerStartedSignal = mIpcService->registerSignalHandler(awokenSignal, awokenHandler);
tests/L1_testing/tests/DobbyProxyTest/CMakeLists.txt:48
IpcVariantList.cppis compiled intoDobbyProxyTestLiband also added to the test executable sources viafile(GLOB ...). That will usually cause duplicate symbol/link errors because the file contains explicit template instantiations. It should only be compiled once (preferably in the library).
file(GLOB TESTS *.cpp
../../mocks/IpcVariantList.cpp
)
client/lib/source/DobbyProxy.cpp:1566
containerStateChangednotifier callbacks are fired for all events, includingContainerStoppedWithStatus. Since the daemon/tests expect bothStoppedandStoppedWithStatusto be emitted for a single container exit, notifier observers will receive duplicate "Stopped" notifications for the same stop event. Consider suppressing notifier emission forContainerStoppedWithStatus(leaving notifier behavior driven by the plainStoppedsignal) to avoid double-delivery.
// fire off via the notifier system first (deprecated but
// required for backwards compatibility)
notify(&IDobbyProxyEvents::containerStateChanged,
event.descriptor, event.name, state);
Description
What does this PR change/fix and why?
RDKEMW-21185: Add exitcode on container stopped event](
Test Procedure
Type of Change
Requires Bitbake Recipe changes?