-
Notifications
You must be signed in to change notification settings - Fork 3k
Error output improvements #8076
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1094c08
78f4b4b
d05c60e
c989845
2df322c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,13 +18,8 @@ | |
#include "platform/mbed_wait_api.h" | ||
#include "platform/mbed_toolchain.h" | ||
#include "platform/mbed_interface.h" | ||
#include "platform/mbed_retarget.h" | ||
#include "platform/mbed_critical.h" | ||
#include "hal/serial_api.h" | ||
|
||
#if DEVICE_SERIAL | ||
extern int stdio_uart_inited; | ||
extern serial_t stdio_uart; | ||
#endif | ||
|
||
WEAK void mbed_die(void) | ||
{ | ||
|
@@ -55,36 +50,41 @@ void mbed_error_printf(const char *format, ...) | |
{ | ||
va_list arg; | ||
va_start(arg, format); | ||
mbed_error_vfprintf(format, arg); | ||
mbed_error_vprintf(format, arg); | ||
va_end(arg); | ||
} | ||
|
||
void mbed_error_vfprintf(const char *format, va_list arg) | ||
void mbed_error_vprintf(const char *format, va_list arg) | ||
{ | ||
#if DEVICE_SERIAL | ||
#define ERROR_BUF_SIZE (128) | ||
core_util_critical_section_enter(); | ||
char buffer[ERROR_BUF_SIZE]; | ||
int size = vsnprintf(buffer, ERROR_BUF_SIZE, format, arg); | ||
if (size > 0) { | ||
if (!stdio_uart_inited) { | ||
serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); | ||
} | ||
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES | ||
char stdio_out_prev = '\0'; | ||
for (int i = 0; i < size; i++) { | ||
if (buffer[i] == '\n' && stdio_out_prev != '\r') { | ||
serial_putc(&stdio_uart, '\r'); | ||
} | ||
serial_putc(&stdio_uart, buffer[i]); | ||
stdio_out_prev = buffer[i]; | ||
char buffer[132]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this buffer size be configurable? Now we have one rare MBED_ASSERT()ion failure in CI, which only logs part of the filename: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does partially address that assert issue; and both a commit I removed and #8255 address the other half. This commit will make that be Which is an improvement - the The commit I used to have here broke the assert up into 4 prints, so it was less likely to overflow and even if the filename was truncated you'd still see the line number. #8255 does the same job by passing through to Still, I can see there may be a desire for bigger buffer. Sadly, I can't see any way to get the "tail" of a printf, so can't break it up in to bits - you need a buffer to hold the entire formatted string. Alternatively, how about avoiding the need for a big buffer by having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was trying to implement and use mbed_error_puts, but I realise now that #8255 does impose its own very heavy truncation. It munges the full filename into its "context" structure, if MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED is on, then outputs that. You might only get the first 16 characters. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having a line number and non-garbage error print is definitely a step forward;). Could the filename trimming be done at mbed_assert_internal(), https://github.com/ARMmbed/mbed-os/blob/master/platform/mbed_assert.c#L25? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, mbed_assert_internal could use puts, or trim itself. But I've pulled back from any changes to that to defer to #8255. But as I said, that introduces a pile of new problems - or at least applies its existing problems to mbed_assert. |
||
int size = vsnprintf(buffer, sizeof buffer, format, arg); | ||
if (size >= sizeof buffer) { | ||
/* Output was truncated - indicate by overwriting last 4 bytes of buffer | ||
* with ellipsis and newline. | ||
* (Note that although vsnprintf always leaves a NUL terminator, we | ||
* don't need a terminator and can use the entire buffer) | ||
*/ | ||
memcpy(&buffer[sizeof buffer - 4], "...\n", 4); | ||
size = sizeof buffer; | ||
} | ||
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES || MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES | ||
char stdio_out_prev = '\0'; | ||
for (int i = 0; i < size; i++) { | ||
if (buffer[i] == '\n' && stdio_out_prev != '\r') { | ||
const char cr = '\r'; | ||
write(STDERR_FILENO, &cr, 1); | ||
} | ||
write(STDERR_FILENO, &buffer[i], 1); | ||
stdio_out_prev = buffer[i]; | ||
} | ||
#else | ||
for (int i = 0; i < size; i++) { | ||
serial_putc(&stdio_uart, buffer[i]); | ||
} | ||
write(STDERR_FILENO, buffer, size); | ||
#endif | ||
} | ||
core_util_critical_section_exit(); | ||
#endif | ||
} | ||
|
||
void mbed_error_vfprintf(const char *format, va_list arg) | ||
{ | ||
mbed_error_vprintf(format, arg); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we advertise after this change, that printf from ISR is valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even after this,
printf
from ISR isn't valid - you'll hit a FILE mutex inside the C library. What may work iswrite(STDERR_FILENO)
, which avoids the C library, but that in turn will depend on what exactly stderr is hooked to.And we don't absolutely stop the user redirecting stderr to a
File
, eg using freopen.The potential
write
from ISR is a "last resort" - it has nothing else it can reasonably do. I don't think we should absolutely require that write to stderr work from interrupts, but we can encourage people to try to use stderr devices that can handle this.