From a2941532bdacba9b8e69dfae4b365aff33f0503a Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Mon, 17 May 2021 17:31:13 +0800 Subject: [PATCH] pthread: Avoid recursive pthread_exit call pthread_exit will be called recursive when pthread_cancel or other cleanup operation with syscalls that support cancellation, to avoid this by mark current tcb flag as TCB_FLAG_CANCEL_DOING instead of TCB_FLAG_CANCEL_PENDING. Signed-off-by: Huang Qi --- sched/pthread/pthread_cancel.c | 3 +-- sched/signal/sig_default.c | 3 +-- sched/task/task_cancelpt.c | 6 ++---- sched/task/task_setcancelstate.c | 3 +-- sched/task/task_setcanceltype.c | 11 +++++------ 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/sched/pthread/pthread_cancel.c b/sched/pthread/pthread_cancel.c index e4088ba8c1..adc2b7eef9 100644 --- a/sched/pthread/pthread_cancel.c +++ b/sched/pthread/pthread_cancel.c @@ -84,10 +84,9 @@ int pthread_cancel(pthread_t thread) if (tcb == this_task()) { -#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags |= TCB_FLAG_CANCEL_DOING; - +#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, PTHREAD_CANCELED); #else diff --git a/sched/signal/sig_default.c b/sched/signal/sig_default.c index 7e87089e57..0078f47687 100644 --- a/sched/signal/sig_default.c +++ b/sched/signal/sig_default.c @@ -224,10 +224,9 @@ static void nxsig_abnormal_termination(int signo) * REVISIT: This will not work if HAVE_GROUP_MEMBERS is not set. */ -#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) rtcb->flags &= ~TCB_FLAG_CANCEL_PENDING; rtcb->flags |= TCB_FLAG_CANCEL_DOING; - +#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) up_pthread_exit(((FAR struct pthread_tcb_s *)rtcb)->exit, PTHREAD_CANCELED); #else diff --git a/sched/task/task_cancelpt.c b/sched/task/task_cancelpt.c index 659e5db6d1..228e90e845 100644 --- a/sched/task/task_cancelpt.c +++ b/sched/task/task_cancelpt.c @@ -140,10 +140,9 @@ bool enter_cancellation_point(void) if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) { -#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags |= TCB_FLAG_CANCEL_DOING; - +#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, PTHREAD_CANCELED); #else @@ -235,10 +234,9 @@ void leave_cancellation_point(void) if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) { -#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags |= TCB_FLAG_CANCEL_DOING; - +#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, PTHREAD_CANCELED); #else diff --git a/sched/task/task_setcancelstate.c b/sched/task/task_setcancelstate.c index 6b61632e99..63f3ef3fa2 100644 --- a/sched/task/task_setcancelstate.c +++ b/sched/task/task_setcancelstate.c @@ -112,10 +112,9 @@ int task_setcancelstate(int state, FAR int *oldstate) if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) { -#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags |= TCB_FLAG_CANCEL_DOING; - +#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, PTHREAD_CANCELED); #else diff --git a/sched/task/task_setcanceltype.c b/sched/task/task_setcanceltype.c index d57cc6408a..f33aeb1fc5 100644 --- a/sched/task/task_setcanceltype.c +++ b/sched/task/task_setcanceltype.c @@ -100,14 +100,13 @@ int task_setcanceltype(int type, FAR int *oldtype) #ifndef CONFIG_DISABLE_PTHREAD if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) { + tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; + tcb->flags |= TCB_FLAG_CANCEL_DOING; #if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) - tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; - tcb->flags |= TCB_FLAG_CANCEL_DOING; - - up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, - PTHREAD_CANCELED); + up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, + PTHREAD_CANCELED); #else - pthread_exit(PTHREAD_CANCELED); + pthread_exit(PTHREAD_CANCELED); #endif } else