Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trap stack overflow with pthread?

I have a C++ application that has a lot of threads and most of them are with 32k of stack size. The problem is that sometimes I get a stackoverflow and I want to detect which thread has caused the stackoverflow and write it on the log file, the problem is that I can't trap it.

I read about the SIGSEGV and I was able to trap this signal only without threads. I also tried using pthread_sigmask() and using the libsigsegv but I also failed.

Can anyone show me a small example about trapping the SIGSEGV when a stack overflow happens in a thread?

like image 414
Hola Soy Edu Feliz Navidad Avatar asked Jan 24 '13 18:01

Hola Soy Edu Feliz Navidad


1 Answers

Trapping stack overflow for a multi-threaded application is, for the most part, not any different from doing so for a single-threaded application. The main way it might be different is if you're overflowing by a large margin; for the main thread; this will still leave you with an invalid stack pointer and SIGSEGV in most cases, but with small thread stacks, the overflow might put your stack pointer in the middle of another thread's stack, in which case very bad things will happen and there's no hope of forward progress. Another issue you should check, if you're using small stacks, is that you didn't disable guard pages. Using pthread_attr_setstack (this function is deprecated, by the way) will not give you guard pages unless you already set them up yourself. Using pthread_attr_setstacksize (the proper modern interface) should not interfere with guard page allocation, but you may want to increase the guard size (with pthread_attr_setguardsize) if you think your overflows are by a large margin.

With that said, the general procedure for handling stack overflow is to setup a handler for SIGSEGV and set it to run on the alternate stack. This last point is critical! As the stack pointer is invalid at the time the signal is generated, there needs to be an alternate stack for the signal handler itself to run on. While the flag for whether a given signal is handled on an alternate stack is a per-signal attribute (set by sigaction), the actual alternate stack is a per-thread attribute. Every thread must set its own alternate stack using sigaltstack. The space for the alternate stack could be allocated via malloc or mmap, but the easiest way to do it is just making an automatic char array of size around 2-4k in the thread start function, and using that for the alternate stack. Basically, what this amounts to doing is reserving a small range at the bottom of the thread's stack to be used as emergency stack space for the signal handler after the top of the stack overflows.

like image 132
R.. GitHub STOP HELPING ICE Avatar answered Nov 02 '22 16:11

R.. GitHub STOP HELPING ICE