From d7deb3fbac6e88d30f9f0295b1737e6850b847a7 Mon Sep 17 00:00:00 2001 From: zhushengle Date: Fri, 13 Aug 2021 10:03:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=BF=9B=E7=A8=8B=E9=80=80=E5=87=BA?= =?UTF-8?q?=E9=9D=99=E6=80=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题描述: 进程在退出过程中,拿到了init_fini_lock锁后被信号打断, 收到退出信号,再次调用exit函数进入进程退出流程,造成死锁 解决方案: 在libc中添加exit字段,在进程退出时将该字段表示进程已经在退出, 若再次进入退出流程,则直接退出,由第一个执行退出流程的线程继续执行 退出流程。并且在退出时屏蔽信号,避免退出流程被频繁打断。 Close #I43V23 Signed-off-by: zhushengle Change-Id: I57b60391267d50c8eb89fc115a26229461bb4ed4 --- porting/liteos_a/user/src/exit/exit.c | 40 +++++++++++++++++++++ porting/liteos_a/user/src/internal/libc.h | 1 + porting/liteos_a/user/src/process/fork.c | 1 + porting/liteos_a/user_debug/src/exit/exit.c | 7 ++++ 4 files changed, 49 insertions(+) create mode 100644 porting/liteos_a/user/src/exit/exit.c diff --git a/porting/liteos_a/user/src/exit/exit.c b/porting/liteos_a/user/src/exit/exit.c new file mode 100644 index 00000000..5001bf12 --- /dev/null +++ b/porting/liteos_a/user/src/exit/exit.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include "libc.h" + +static void dummy() +{ +} + +/* atexit.c and __stdio_exit.c override these. the latter is linked + * as a consequence of linking either __toread.c or __towrite.c. */ +weak_alias(dummy, __funcs_on_exit); +weak_alias(dummy, __stdio_exit); +weak_alias(dummy, _fini); + +extern weak hidden void (*const __fini_array_start)(void), (*const __fini_array_end)(void); + +static void libc_exit_fini(void) +{ + uintptr_t a = (uintptr_t)&__fini_array_end; + for (; a>(uintptr_t)&__fini_array_start; a-=sizeof(void(*)())) + (*(void (**)())(a-sizeof(void(*)())))(); + _fini(); +} + +weak_alias(libc_exit_fini, __libc_exit_fini); + +_Noreturn void exit(int code) +{ + sigset_t set; + if (a_cas(&libc.exit, 0, 1) != 0) { + return; + } + __block_app_sigs(&set); + __funcs_on_exit(); + __libc_exit_fini(); + __stdio_exit(); + _Exit(code); +} diff --git a/porting/liteos_a/user/src/internal/libc.h b/porting/liteos_a/user/src/internal/libc.h index da237ed1..759f5b8a 100644 --- a/porting/liteos_a/user/src/internal/libc.h +++ b/porting/liteos_a/user/src/internal/libc.h @@ -27,6 +27,7 @@ struct __libc { size_t tls_size, tls_align, tls_cnt; size_t page_size; struct __locale_struct global_locale; + int exit; }; #ifndef PAGE_SIZE diff --git a/porting/liteos_a/user/src/process/fork.c b/porting/liteos_a/user/src/process/fork.c index b5b8dca0..160ef5d2 100644 --- a/porting/liteos_a/user/src/process/fork.c +++ b/porting/liteos_a/user/src/process/fork.c @@ -30,6 +30,7 @@ pid_t fork(void) self->next = self->prev = self; __thread_list_lock = 0; libc.threads_minus_1 = 0; + libc.exit = 0; signal(SIGSYS, arm_do_signal); } __restore_sigs(&set); diff --git a/porting/liteos_a/user_debug/src/exit/exit.c b/porting/liteos_a/user_debug/src/exit/exit.c index 5d2d00a3..945da520 100644 --- a/porting/liteos_a/user_debug/src/exit/exit.c +++ b/porting/liteos_a/user_debug/src/exit/exit.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "libc.h" extern bool g_enable_check; @@ -32,6 +34,11 @@ weak_alias(libc_exit_fini, __libc_exit_fini); _Noreturn void exit(int code) { + sigset_t set; + if (a_cas(&libc.exit, 0, 1) != 0) { + return; + } + __block_app_sigs(&set); if (g_enable_check) { check_leak(); check_heap_integrity(); -- GitLab