mirror of https://github.com/ARMmbed/mbed-os.git
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.pull/10358/head
parent
aa0e86475c
commit
b8e80dd2fb
|
@ -45,7 +45,7 @@ static void print_error_report(const mbed_error_ctx *ctx, const char *, const ch
|
|||
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
|
||||
#endif
|
||||
|
||||
static core_util_atomic_flag error_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
|
||||
static bool error_in_progress;
|
||||
static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
|
||||
static int error_count = 0;
|
||||
static mbed_error_ctx first_error_ctx = {0};
|
||||
|
@ -115,7 +115,7 @@ static MBED_NORETURN void mbed_halt_system(void)
|
|||
WEAK MBED_NORETURN void error(const char *format, ...)
|
||||
{
|
||||
// Prevent recursion if error is called again during store+print attempt
|
||||
if (!core_util_atomic_flag_test_and_set(&error_in_progress)) {
|
||||
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
|
||||
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
|
||||
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
|
||||
|
||||
|
@ -256,6 +256,12 @@ int mbed_get_error_count(void)
|
|||
return error_count;
|
||||
}
|
||||
|
||||
//Reads the fatal error occurred" flag
|
||||
bool mbed_get_error_in_progress(void)
|
||||
{
|
||||
return core_util_atomic_load_bool(&error_in_progress);
|
||||
}
|
||||
|
||||
//Sets a non-fatal error
|
||||
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)
|
||||
{
|
||||
|
@ -266,7 +272,7 @@ mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *e
|
|||
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)
|
||||
{
|
||||
// Prevent recursion if error is called again during store+print attempt
|
||||
if (!core_util_atomic_flag_test_and_set(&error_in_progress)) {
|
||||
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
|
||||
//set the error reported
|
||||
(void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#ifndef MBED_ERROR_H
|
||||
#define MBED_ERROR_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "platform/mbed_retarget.h"
|
||||
#include "platform/mbed_toolchain.h"
|
||||
|
||||
|
@ -1036,6 +1037,13 @@ mbed_error_status_t mbed_get_last_error(void);
|
|||
*/
|
||||
int mbed_get_error_count(void);
|
||||
|
||||
/**
|
||||
* Returns whether we are processing a fatal mbed error.
|
||||
* @return bool Whether a fatal error has occurred.
|
||||
*
|
||||
*/
|
||||
bool mbed_get_error_in_progress(void);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -47,7 +47,10 @@ void Mutex::constructor(const char *name)
|
|||
attr.cb_size = sizeof(_obj_mem);
|
||||
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
_id = osMutexNew(&attr);
|
||||
MBED_ASSERT(_id);
|
||||
// To permit certain cases where a device may get constructed in
|
||||
// by the attempt to print an error in a fatal shutdown, let a
|
||||
// mutex construction error pass.
|
||||
MBED_ASSERT(_id || mbed_get_error_in_progress());
|
||||
}
|
||||
|
||||
osStatus Mutex::lock(void)
|
||||
|
@ -57,7 +60,7 @@ osStatus Mutex::lock(void)
|
|||
_count++;
|
||||
}
|
||||
|
||||
if (status != osOK) {
|
||||
if (status != osOK && !mbed_get_error_in_progress()) {
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status);
|
||||
}
|
||||
|
||||
|
@ -75,7 +78,7 @@ osStatus Mutex::lock(uint32_t millisec)
|
|||
(status == osErrorResource && millisec == 0) ||
|
||||
(status == osErrorTimeout && millisec != osWaitForever));
|
||||
|
||||
if (!success) {
|
||||
if (!success && !mbed_get_error_in_progress()) {
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status);
|
||||
}
|
||||
|
||||
|
@ -98,7 +101,7 @@ bool Mutex::trylock_for(uint32_t millisec)
|
|||
(status == osErrorResource && millisec == 0) ||
|
||||
(status == osErrorTimeout && millisec != osWaitForever));
|
||||
|
||||
if (!success) {
|
||||
if (!success && !mbed_get_error_in_progress()) {
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "Mutex lock failed", status);
|
||||
}
|
||||
|
||||
|
@ -121,15 +124,16 @@ bool Mutex::trylock_until(uint64_t millisec)
|
|||
|
||||
osStatus Mutex::unlock()
|
||||
{
|
||||
_count--;
|
||||
|
||||
osStatus status = osMutexRelease(_id);
|
||||
if (osOK == status) {
|
||||
_count--;
|
||||
}
|
||||
|
||||
if (status != osOK) {
|
||||
if (status != osOK && !mbed_get_error_in_progress()) {
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_UNLOCK_FAILED), "Mutex unlock failed", status);
|
||||
}
|
||||
|
||||
return osOK;
|
||||
return status;
|
||||
}
|
||||
|
||||
osThreadId Mutex::get_owner()
|
||||
|
|
|
@ -107,29 +107,40 @@ static const char *error_msg(int32_t status)
|
|||
}
|
||||
}
|
||||
|
||||
static void trap_rtx_error(unsigned int error_value, int32_t rtx_status, mbed_error_status_t error_status)
|
||||
{
|
||||
// Attempts to get the console for the first time while printing an error
|
||||
// may well cause a mutex error; in general let RTX calls fail during
|
||||
// an error condition.
|
||||
if (mbed_get_error_in_progress()) {
|
||||
return;
|
||||
}
|
||||
MBED_ERROR1(error_status, error_msg(rtx_status), error_value);
|
||||
}
|
||||
|
||||
void EvrRtxKernelError(int32_t status)
|
||||
{
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT), error_msg(status), status);
|
||||
trap_rtx_error(status, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT));
|
||||
}
|
||||
|
||||
void EvrRtxThreadError(osThreadId_t thread_id, int32_t status)
|
||||
{
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_THREAD_EVENT), error_msg(status), thread_id);
|
||||
trap_rtx_error((unsigned int) thread_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_THREAD_EVENT));
|
||||
}
|
||||
|
||||
void EvrRtxTimerError(osTimerId_t timer_id, int32_t status)
|
||||
{
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_TIMER_EVENT), error_msg(status), timer_id);
|
||||
trap_rtx_error((unsigned int) timer_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_TIMER_EVENT));
|
||||
}
|
||||
|
||||
void EvrRtxEventFlagsError(osEventFlagsId_t ef_id, int32_t status)
|
||||
{
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT), error_msg(status), ef_id);
|
||||
trap_rtx_error((unsigned int) ef_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT));
|
||||
}
|
||||
|
||||
void EvrRtxMutexError(osMutexId_t mutex_id, int32_t status)
|
||||
{
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MUTEX_EVENT), error_msg(status), mutex_id);
|
||||
trap_rtx_error((unsigned int) mutex_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MUTEX_EVENT));
|
||||
}
|
||||
|
||||
void EvrRtxSemaphoreError(osSemaphoreId_t semaphore_id, int32_t status)
|
||||
|
@ -139,17 +150,17 @@ void EvrRtxSemaphoreError(osSemaphoreId_t semaphore_id, int32_t status)
|
|||
return;
|
||||
}
|
||||
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT), error_msg(status), semaphore_id);
|
||||
trap_rtx_error((unsigned int) semaphore_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT));
|
||||
}
|
||||
|
||||
void EvrRtxMemoryPoolError(osMemoryPoolId_t mp_id, int32_t status)
|
||||
{
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT), error_msg(status), mp_id);
|
||||
trap_rtx_error((unsigned int) mp_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT));
|
||||
}
|
||||
|
||||
void EvrRtxMessageQueueError(osMessageQueueId_t mq_id, int32_t status)
|
||||
{
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT), error_msg(status), mq_id);
|
||||
trap_rtx_error((unsigned int) mq_id, status, MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue