From 8f57c61da9447a0fb69f6801ac7e44f2a4756a5c Mon Sep 17 00:00:00 2001 From: Yin Fengwei Date: Mon, 17 Dec 2018 10:26:47 +0800 Subject: [PATCH] dm: Add teardown callback for mevent in uart_core To avoid the race issue for mevent in uart, we introduce the teardown callback to handle resource free case. Tracked-On: #1877 Signed-off-by: Yin Fengwei Acked-by: Yu Wang --- devicemodel/hw/uart_core.c | 43 ++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/devicemodel/hw/uart_core.c b/devicemodel/hw/uart_core.c index 0f63bb359..5b4e79aee 100644 --- a/devicemodel/hw/uart_core.c +++ b/devicemodel/hw/uart_core.c @@ -119,6 +119,7 @@ struct uart_vdev { }; static void uart_drain(int fd, enum ev_type ev, void *arg); +static void uart_deinit(struct uart_vdev *uart); static void ttyclose(void) @@ -266,12 +267,34 @@ rxfifo_numchars(struct uart_vdev *uart) return fifo->num; } +static void +uart_mevent_teardown(void *param) +{ + struct uart_vdev *uart = param; + + uart->mev = 0; + ttyclose(); + + if (uart->tty.fd_in == STDIN_FILENO) { + stdio_in_use = false; + } else { + close(uart->tty.fd_in); + } + + uart->tty.fd_in = -1; + uart->tty.fd_out = -1; + uart->tty.opened = false; + + uart_deinit(uart); +} + static void uart_opentty(struct uart_vdev *uart) { ttyopen(&uart->tty); if (isatty(uart->tty.fd_in)) { - uart->mev = mevent_add(uart->tty.fd_in, EVF_READ, uart_drain, uart, NULL, NULL); + uart->mev = mevent_add(uart->tty.fd_in, EVF_READ, + uart_drain, uart, uart_mevent_teardown, uart); assert(uart->mev != NULL); } } @@ -284,11 +307,10 @@ uart_closetty(struct uart_vdev *uart) mevent_delete_close(uart->mev); else mevent_delete(uart->mev); - - uart->mev = 0; + /* uart deinit will be invoked in mevent teardown callback */ + } else { + uart_mevent_teardown(uart); } - - ttyclose(); } static uint8_t @@ -718,7 +740,6 @@ uart_set_backend(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, goto fail_tty_backend; uart_opentty(uart); - return uart; fail_tty_backend: @@ -749,14 +770,4 @@ uart_release_backend(struct uart_vdev *uart, const char *opts) return; uart_closetty(uart); - if (strcmp("stdio", opts) == 0) { - stdio_in_use = false; - } else - close(uart->tty.fd_in); - - uart->tty.fd_in = -1; - uart->tty.fd_out = -1; - uart->tty.opened = false; - - uart_deinit(uart); }