There's a debug option called CONFIG_DEBUG_STACKOVERFLOW which might help you catch stack overflows before they bite you and crash your kernel.
However, this is implemented in an arch-specific way inside the interrupt handling. As v4.6, the architectures that support this are:
$ git grep "select HAVE_DEBUG_STACKOVERFLOW" v4.6
v4.6:arch/arc/Kconfig:  select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/blackfin/Kconfig:     select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/frv/Kconfig:  select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/m32r/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/metag/Kconfig:        select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/mips/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/mn10300/Kconfig:      select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/openrisc/Kconfig:     select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/parisc/Kconfig:       select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/powerpc/Kconfig:      select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/tile/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/x86/Kconfig:  select HAVE_DEBUG_STACKOVERFLOW
Notably, ARM is not on that list.
It is interesting to see how simple it is to check the current stack depth:
/* Debugging check for stack overflow: is there less than 1KB free? */
static int check_stack_overflow(void)
{
        long sp;
        __asm__ __volatile__("andl %%esp,%0" :
                             "=r" (sp) : "0" (THREAD_SIZE - 1));
        return sp < (sizeof(struct thread_info) + STACK_WARN);
}
Now, regarding your question about recursion: it is a poor design in kernel development, for precisely the issue you are facing. In kernel land, the stack is fixed and won't grow. Recursion is usually stack-hungry and will lead you to stack overflowing easily.
Keep in mind that theoretically you can always convert a recursive algorithm to an iterative one, as explained here:  Can every recursion be converted into iteration?