stmhal: Improve handling of out-of-memory in REPL.

Addresses issue #558, but it's likely that other out-of-memory errors
could crash the pyboard.  Reason is that qstrs use m_new and can raise
an exception within the parser.
This commit is contained in:
Damien George 2014-05-10 17:48:46 +01:00
parent e1199ecf10
commit b0edec61ac
2 changed files with 22 additions and 9 deletions

View File

@ -163,7 +163,11 @@ raw_repl_reset:
} }
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0); mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0);
parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false); if (lex == NULL) {
printf("MemoryError\n");
} else {
parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false);
}
// indicate end of output with EOF character // indicate end of output with EOF character
stdout_tx_str("\004"); stdout_tx_str("\004");
@ -239,7 +243,11 @@ friendly_repl_reset:
} }
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0); mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0);
parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, true); if (lex == NULL) {
printf("MemoryError\n");
} else {
parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, true);
}
} }
} }

View File

@ -55,11 +55,13 @@ void readline_init(void) {
memset(readline_hist, 0, READLINE_HIST_SIZE * sizeof(const char*)); memset(readline_hist, 0, READLINE_HIST_SIZE * sizeof(const char*));
} }
STATIC char *str_dup(const char *str) { STATIC char *str_dup_maybe(const char *str) {
uint32_t len = strlen(str); uint32_t len = strlen(str);
char *s2 = m_new(char, len + 1); char *s2 = m_new_maybe(char, len + 1);
memcpy(s2, str, len); if (s2 == NULL) {
s2[len] = 0; return NULL;
}
memcpy(s2, str, len + 1);
return s2; return s2;
} }
@ -92,10 +94,13 @@ int readline(vstr_t *line, const char *prompt) {
if (line->len > orig_line_len && (readline_hist[0] == NULL || strcmp(readline_hist[0], line->buf + orig_line_len) != 0)) { if (line->len > orig_line_len && (readline_hist[0] == NULL || strcmp(readline_hist[0], line->buf + orig_line_len) != 0)) {
// a line which is not empty and different from the last one // a line which is not empty and different from the last one
// so update the history // so update the history
for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { char *most_recent_hist = str_dup_maybe(line->buf + orig_line_len);
readline_hist[i] = readline_hist[i - 1]; if (most_recent_hist != NULL) {
for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) {
readline_hist[i] = readline_hist[i - 1];
}
readline_hist[0] = most_recent_hist;
} }
readline_hist[0] = str_dup(line->buf + orig_line_len);
} }
return 0; return 0;
} else if (c == 27) { } else if (c == 27) {