Skip to content

Commit b8e80dd

Browse files
committed
Don't trap RTX errors or mutex errors during errors
Once a fatal error is in progress, it's not useful to trap RTX errors or mutex problems, so short-circuit the checks. This makes it more likely that we may be able to get the console initialised if it is being written to for the first time by `mbed_error` in a difficult context - such as an RTX error callback from inside an SVCall. For example, the one-line program osMutexAcquire(NULL, 0); will generate an RTX error trap, then `mbed_error` will try to call `write(STDERR_FILENO)` to print the error, which will prompt mbed_retarget to construct a singleton `UARTSerial`. This would trap in the mutex for the singleton or the construction of the UARTSerial itself, if we didn't allow this leniency. If we clear the mutex checks, then `UARTSerial::write_unbuffered` will work.
1 parent aa0e864 commit b8e80dd

File tree

4 files changed

+48
-19
lines changed

4 files changed

+48
-19
lines changed

platform/mbed_error.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static void print_error_report(const mbed_error_ctx *ctx, const char *, const ch
4545
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
4646
#endif
4747

48-
static core_util_atomic_flag error_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
48+
static bool error_in_progress;
4949
static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
5050
static int error_count = 0;
5151
static mbed_error_ctx first_error_ctx = {0};
@@ -115,7 +115,7 @@ static MBED_NORETURN void mbed_halt_system(void)
115115
WEAK MBED_NORETURN void error(const char *format, ...)
116116
{
117117
// Prevent recursion if error is called again during store+print attempt
118-
if (!core_util_atomic_flag_test_and_set(&error_in_progress)) {
118+
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
119119
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
120120
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
121121

@@ -256,6 +256,12 @@ int mbed_get_error_count(void)
256256
return error_count;
257257
}
258258

259+
//Reads the fatal error occurred" flag
260+
bool mbed_get_error_in_progress(void)
261+
{
262+
return core_util_atomic_load_bool(&error_in_progress);
263+
}
264+
259265
//Sets a non-fatal error
260266
mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
261267
{
@@ -266,7 +272,7 @@ mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *e
266272
WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
267273
{
268274
// Prevent recursion if error is called again during store+print attempt
269-
if (!core_util_atomic_flag_test_and_set(&error_in_progress)) {
275+
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
270276
//set the error reported
271277
(void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
272278

platform/mbed_error.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#ifndef MBED_ERROR_H
2424
#define MBED_ERROR_H
2525

26+
#include <stdbool.h>
2627
#include "platform/mbed_retarget.h"
2728
#include "platform/mbed_toolchain.h"
2829

@@ -1036,6 +1037,13 @@ mbed_error_status_t mbed_get_last_error(void);
10361037
*/
10371038
int mbed_get_error_count(void);
10381039

1040+
/**
1041+
* Returns whether we are processing a fatal mbed error.
1042+
* @return bool Whether a fatal error has occurred.
1043+
*
1044+
*/
1045+
bool mbed_get_error_in_progress(void);
1046+
10391047
/**
10401048
* Call this function to set a fatal system error and halt the system. This function will log the fatal error with the context info and prints the error report and halts the system.
10411049
*

rtos/Mutex.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ void Mutex::constructor(const char *name)
4747
attr.cb_size = sizeof(_obj_mem);
4848
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
4949
_id = osMutexNew(&attr);
50-
MBED_ASSERT(_id);
50+
// To permit certain cases where a device may get constructed in
51+
// by the attempt to print an error in a fatal shutdown, let a
52+
// mutex construction error pass.
53+
MBED_ASSERT(_id || mbed_get_error_in_progress());
5154
}
5255

5356
osStatus Mutex::lock(void)
@@ -57,7 +60,7 @@ osStatus Mutex::lock(void)
5760
_count++;
5861
}
5962

60-
if (status != osOK) {
63+
if (status != osOK && !mbed_get_error_in_progress()) {
6164
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status);
6265
}
6366

@@ -75,7 +78,7 @@ osStatus Mutex::lock(uint32_t millisec)
7578
(status == osErrorResource && millisec == 0) ||
7679
(status == osErrorTimeout && millisec != osWaitForever));
7780

78-
if (!success) {
81+
if (!success && !mbed_get_error_in_progress()) {
7982
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status);
8083
}
8184

@@ -98,7 +101,7 @@ bool Mutex::trylock_for(uint32_t millisec)
98101
(status == osErrorResource && millisec == 0) ||
99102
(status == osErrorTimeout && millisec != osWaitForever));
100103

101-
if (!success) {
104+
if (!success && !mbed_get_error_in_progress()) {
102105
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status);
103106
}
104107

@@ -121,15 +124,16 @@ bool Mutex::trylock_until(uint64_t millisec)
121124

122125
osStatus Mutex::unlock()
123126
{
124-
_count--;
125-
126127
osStatus status = osMutexRelease(_id);
128+
if (osOK == status) {
129+
_count--;
130+
}
127131

128-
if (status != osOK) {
132+
if (status != osOK && !mbed_get_error_in_progress()) {
129133
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_UNLOCK_FAILED), "Mutex unlock failed", status);
130134
}
131135

132-
return osOK;
136+
return status;
133137
}
134138

135139
osThreadId Mutex::get_owner()

rtos/TARGET_CORTEX/mbed_rtx_handlers.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,29 +107,40 @@ static const char *error_msg(int32_t status)
107107
}
108108
}
109109

110+
static void trap_rtx_error(unsigned int error_value, int32_t rtx_status, mbed_error_status_t error_status)
111+
{
112+
// Attempts to get the console for the first time while printing an error
113+
// may well cause a mutex error; in general let RTX calls fail during
114+
// an error condition.
115+
if (mbed_get_error_in_progress()) {
116+
return;
117+
}
118+
MBED_ERROR1(error_status, error_msg(rtx_status), error_value);
119+
}
120+
110121
void EvrRtxKernelError(int32_t status)
111122
{
112-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT), error_msg(status), status);
123+
trap_rtx_error(status, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT));
113124
}
114125

115126
void EvrRtxThreadError(osThreadId_t thread_id, int32_t status)
116127
{
117-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_THREAD_EVENT), error_msg(status), thread_id);
128+
trap_rtx_error((unsigned int) thread_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_THREAD_EVENT));
118129
}
119130

120131
void EvrRtxTimerError(osTimerId_t timer_id, int32_t status)
121132
{
122-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_TIMER_EVENT), error_msg(status), timer_id);
133+
trap_rtx_error((unsigned int) timer_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_TIMER_EVENT));
123134
}
124135

125136
void EvrRtxEventFlagsError(osEventFlagsId_t ef_id, int32_t status)
126137
{
127-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT), error_msg(status), ef_id);
138+
trap_rtx_error((unsigned int) ef_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT));
128139
}
129140

130141
void EvrRtxMutexError(osMutexId_t mutex_id, int32_t status)
131142
{
132-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MUTEX_EVENT), error_msg(status), mutex_id);
143+
trap_rtx_error((unsigned int) mutex_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MUTEX_EVENT));
133144
}
134145

135146
void EvrRtxSemaphoreError(osSemaphoreId_t semaphore_id, int32_t status)
@@ -139,17 +150,17 @@ void EvrRtxSemaphoreError(osSemaphoreId_t semaphore_id, int32_t status)
139150
return;
140151
}
141152

142-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT), error_msg(status), semaphore_id);
153+
trap_rtx_error((unsigned int) semaphore_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT));
143154
}
144155

145156
void EvrRtxMemoryPoolError(osMemoryPoolId_t mp_id, int32_t status)
146157
{
147-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT), error_msg(status), mp_id);
158+
trap_rtx_error((unsigned int) mp_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT));
148159
}
149160

150161
void EvrRtxMessageQueueError(osMessageQueueId_t mq_id, int32_t status)
151162
{
152-
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT), error_msg(status), mq_id);
163+
trap_rtx_error((unsigned int) mq_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT));
153164
}
154165

155166
#endif

0 commit comments

Comments
 (0)