diff --git a/src/kern/core/hev-task-system-private.h b/src/kern/core/hev-task-system-private.h index 0811383..611fa4b 100644 --- a/src/kern/core/hev-task-system-private.h +++ b/src/kern/core/hev-task-system-private.h @@ -51,9 +51,7 @@ struct _HevTaskSystemContext jmp_buf kernel_context; -#ifdef ENABLE_DEBUG HevList all_tasks; -#endif }; void hev_task_system_schedule (HevTaskYieldType type); diff --git a/src/kern/core/hev-task-system.c b/src/kern/core/hev-task-system.c index 3f771f9..08a179c 100644 --- a/src/kern/core/hev-task-system.c +++ b/src/kern/core/hev-task-system.c @@ -11,6 +11,7 @@ #include #include "lib/misc/hev-compiler.h" +#include "lib/misc/hev-task-stack-detector.h" #include "mem/api/hev-memory-allocator-api.h" #include "mem/slice/hev-memory-allocator-slice.h" @@ -72,8 +73,13 @@ hev_task_system_init (void) if (!context->timer) goto free_reactor; + if (hev_task_stack_detector_init () < 0) + goto free_timer; + return 0; +free_timer: + hev_task_timer_destroy (context->timer); free_reactor: hev_task_io_reactor_destroy (context->reactor); rest_context: @@ -92,6 +98,7 @@ hev_task_system_fini (void) if (context->dns_proxy) hev_task_dns_proxy_destroy (context->dns_proxy); + hev_task_stack_detector_fini (); hev_task_timer_destroy (context->timer); hev_task_io_reactor_destroy (context->reactor); hev_free (context); diff --git a/src/kern/task/hev-task-private.h b/src/kern/task/hev-task-private.h index 020ded8..fbda24d 100644 --- a/src/kern/task/hev-task-private.h +++ b/src/kern/task/hev-task-private.h @@ -45,9 +45,7 @@ struct _HevTask jmp_buf context; -#ifdef ENABLE_DEBUG HevListNode list_node; -#endif }; extern void hev_task_execute (HevTask *self, void *executer); diff --git a/src/kern/task/hev-task.c b/src/kern/task/hev-task.c index 9cab9e2..164a318 100644 --- a/src/kern/task/hev-task.c +++ b/src/kern/task/hev-task.c @@ -44,10 +44,8 @@ hev_task_new (int stack_size) self->stack_bottom = hev_task_stack_get_bottom (self->stack); self->sched_entity.task = self; -#ifdef ENABLE_DEBUG hev_list_add_tail (&hev_task_system_get_context ()->all_tasks, &self->list_node); -#endif return self; } @@ -67,9 +65,7 @@ hev_task_unref (HevTask *self) if (self->ref_count) return; -#ifdef ENABLE_DEBUG hev_list_del (&hev_task_system_get_context ()->all_tasks, &self->list_node); -#endif hev_task_stack_destroy (self->stack); hev_free (self); diff --git a/src/lib/misc/hev-task-stack-detector.c b/src/lib/misc/hev-task-stack-detector.c new file mode 100644 index 0000000..71ff7a5 --- /dev/null +++ b/src/lib/misc/hev-task-stack-detector.c @@ -0,0 +1,103 @@ +/* + ============================================================================ + Name : hev-task-stack-detector.c + Author : hev + Copyright : Copyright (c) 2024 hev. + Description : Task Stack Overflow Detector + ============================================================================ + */ + +#include +#include + +#if defined(__APPLE__) +#include +#include +#include +#endif + +#include "kern/core/hev-task-system-private.h" +#include "kern/task/hev-task-private.h" +#include "kern/task/hev-task-stack.h" +#include "lib/misc/hev-compiler.h" + +#include "hev-task-stack-detector.h" + +static struct sigaction bus_sa; +static struct sigaction segv_sa; +static char stack[SIGSTKSZ]; +static stack_t oss; + +static int +setaltstack (const stack_t *ss, stack_t *oss) +{ +#if defined(TARGET_OS_TV) && TARGET_OS_TV + return 0; +#else + return sigaltstack (ss, oss); +#endif +} + +static void +signal_handler (int signo, siginfo_t *si, void *unused) +{ + HevTaskSystemContext *context = hev_task_system_get_context (); + HevListNode *node = hev_list_first (&context->all_tasks); + + for (; node; node = hev_list_node_next (node)) { + HevTask *task = container_of (node, HevTask, list_node); + const void *stack_base, *stack_bottom; + + stack_base = hev_task_stack_get_base (task->stack); + stack_bottom = hev_task_stack_get_bottom (task->stack); + + if (stack_base <= si->si_addr && si->si_addr <= stack_bottom) { + fprintf (stderr, "========== Oops! Stack overflow! ==========\n"); + fprintf (stderr, "Task: %p\n", task); + fprintf (stderr, " Stack : %p - %p\n", stack_base, stack_bottom); + fprintf (stderr, " Bad addr: %p\n", si->si_addr); + fprintf (stderr, "===========================================\n"); + } + } + + switch (signo) { + case SIGBUS: + bus_sa.sa_sigaction (signo, si, unused); + break; + case SIGSEGV: + segv_sa.sa_sigaction (signo, si, unused); + break; + default: + return; + } +} + +int +hev_task_stack_detector_init (void) +{ + struct sigaction sa; + int res = 0; + stack_t ss; + + ss.ss_size = SIGSTKSZ; + ss.ss_sp = stack; + ss.ss_flags = 0; + + sa.sa_flags = SA_SIGINFO | SA_ONSTACK; + sa.sa_sigaction = signal_handler; + sigemptyset (&sa.sa_mask); + + res |= setaltstack (&ss, &oss); + res |= sigaction (SIGBUS, &sa, &bus_sa); + res |= sigaction (SIGSEGV, &sa, &segv_sa); + + return res; +} + +void +hev_task_stack_detector_fini (void) +{ + sigaction (SIGBUS, &bus_sa, NULL); + sigaction (SIGSEGV, &segv_sa, NULL); + setaltstack (&oss, NULL); +} diff --git a/src/lib/misc/hev-task-stack-detector.h b/src/lib/misc/hev-task-stack-detector.h new file mode 100644 index 0000000..1a83ff1 --- /dev/null +++ b/src/lib/misc/hev-task-stack-detector.h @@ -0,0 +1,16 @@ +/* + ============================================================================ + Name : hev-task-stack-detector.h + Author : hev + Copyright : Copyright (c) 2024 hev. + Description : Task Stack Overflow Detector + ============================================================================ + */ + +#ifndef __HEV_TASK_STACK_DETECTOR_H__ +#define __HEV_TASK_STACK_DETECTOR_H__ + +int hev_task_stack_detector_init (void); +void hev_task_stack_detector_fini (void); + +#endif /* __HEV_TASK_STACK_DETECTOR_H__ */