pw_thread_embos: Keep walking tasks on error
Changes behavior of the thread iterator to continue iteration over all
threads when an error is encountered.
Change-Id: I9a4dae78f277d8de69a59dc67212a1184ff33e64
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/53660
Pigweed-Auto-Submit: Armando Montanez <amontanez@google.com>
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/pw_thread_embos/docs.rst b/pw_thread_embos/docs.rst
index abd599a..2328ef3 100644
--- a/pw_thread_embos/docs.rst
+++ b/pw_thread_embos/docs.rst
@@ -161,14 +161,16 @@
the scheduler has started is non-fatal, but will result in no action and a
``FailedPrecondition`` error code.
+An ``Aborted`` error status is returned if the provided callback returns
+``false`` to request an early termination of thread iteration.
+
Return values
-------------
* ``FailedPrecondition``: Returned when ``ForEachThread()`` is run before the OS
has been initialized.
+* ``Aborted``: The callback requested an early-termination of thread iteration.
* ``OkStatus``: The callback has been successfully run with every thread.
-* Other: The callback returned an error status on a thread, triggering an early
- abort.
--------------------
Snapshot Integration
diff --git a/pw_thread_embos/public/pw_thread_embos/util.h b/pw_thread_embos/public/pw_thread_embos/util.h
index 7d5cb95..8fdfd90 100644
--- a/pw_thread_embos/public/pw_thread_embos/util.h
+++ b/pw_thread_embos/public/pw_thread_embos/util.h
@@ -19,20 +19,22 @@
namespace pw::thread::embos {
-// A callback that is executed for each thread when using ForEachThread().
-using ThreadCallback = pw::Function<Status(const OS_TASK&)>;
+// A callback that is executed for each thread when using ForEachThread(). The
+// callback should return true if thread iteration should continue. When this
+// callback returns false, ForEachThread() will cease iteration of threads and
+// return an `Aborted` error code.
+using ThreadCallback = pw::Function<bool(const OS_TASK&)>;
// Iterates through all threads that haven't been deleted, calling the provided
-// callback on each thread. If the callback fails on one thread, the iteration
-// stops.
+// callback on each thread.
//
// Precondition:
// OS_Start() must be called prior to using this function.
//
// Returns:
// FailedPrecondition - The scheduler has not yet been initialized.
+// Aborted - The callback requested an early-termination of thread iteration.
// OkStatus - Successfully iterated over all threads.
-// Other statuses may be returned by the ThreadCallback.
//
// Warning: This is only safe to use when the scheduler is disabled.
Status ForEachThread(ThreadCallback& cb);
diff --git a/pw_thread_embos/snapshot.cc b/pw_thread_embos/snapshot.cc
index 4e2c037..3bf1268 100644
--- a/pw_thread_embos/snapshot.cc
+++ b/pw_thread_embos/snapshot.cc
@@ -72,20 +72,29 @@
void* running_thread_stack_pointer;
SnapshotThreadInfo::StreamEncoder* encoder;
ProcessThreadStackCallback* stack_dumper;
+ Status thread_capture_status;
} ctx;
ctx.running_thread_stack_pointer = running_thread_stack_pointer;
ctx.encoder = &encoder;
ctx.stack_dumper = &stack_dumper;
- ThreadCallback thread_capture_cb([&ctx](const OS_TASK& thread) -> Status {
+ ThreadCallback thread_capture_cb([&ctx](const OS_TASK& thread) -> bool {
Thread::StreamEncoder thread_encoder = ctx.encoder->GetThreadsEncoder();
- return SnapshotThread(thread,
- ctx.running_thread_stack_pointer,
- thread_encoder,
- *ctx.stack_dumper);
+ ctx.thread_capture_status.Update(
+ SnapshotThread(thread,
+ ctx.running_thread_stack_pointer,
+ thread_encoder,
+ *ctx.stack_dumper));
+ // Always iterate all threads.
+ return true;
});
- return ForEachThread(thread_capture_cb);
+ if (Status status = ForEachThread(thread_capture_cb); !status.ok()) {
+ PW_LOG_ERROR("Failed to iterate threads during snapshot capture: %d",
+ static_cast<int>(status.code()));
+ }
+
+ return ctx.thread_capture_status;
}
Status SnapshotThread(const OS_TASK& thread,
diff --git a/pw_thread_embos/util.cc b/pw_thread_embos/util.cc
index c565460..31b0713 100644
--- a/pw_thread_embos/util.cc
+++ b/pw_thread_embos/util.cc
@@ -16,7 +16,6 @@
#include "RTOS.h"
#include "pw_function/function.h"
#include "pw_status/status.h"
-#include "pw_status/try.h"
namespace pw::thread::embos {
@@ -31,7 +30,10 @@
const OS_TASK* thread = &starting_thread;
while (thread != nullptr) {
- PW_TRY(cb(*thread));
+ if (!cb(*thread)) {
+ // Early-terminate iteration if requested by the callback.
+ return Status::Aborted();
+ }
thread = thread->pNext;
}