[Ur] Could we prevent most segmentation faults caused by stack overflows this way?

Marc Weber marco-oweber at gmx.de
Tue Dec 21 21:42:54 EST 2010


Excerpts from Adam Chlipala's message of Mon Dec 20 15:09:03 +0100 2010:
> Standard C doesn't provide a way to catch stack overflows, as far as I 
> know.  I've made some experiments with Linux-specific code, but I didn't 
> end up satisfied.  If you can suggest a particular implementation 
> technique (ideally one that will work on all platforms), I'd be glad to 
> use it.

is:    shows approximation of current stack pointer
start: shows start of stack
The head output shows approximately the total stack size 8377528
The tail output shows the last two lines before the stack overflow
happens:

  %./test | head -n 1
  is: ad1bd4b8 between? 1 start: ac9c0000 next : 5a37a970, left: 8377528 

  %./test | tail -n 2
  is: 77b8f1e8 between? 1 start: 77b8e000 next : 77b8f198, left: 4584 
  is: 77b8f198 between? 1 zsh: segmentation fault  ./test | 

Would something like this work reasonable?

Its using pthread to get stack size (this was used to tell the ruby
garbage collector which memory to scan. After telling about it the
ruby gc related segfaults were gone)

This calculates the left: value:
  ((long int) current) - ((long int) start

If you have multiple threads its very bad that one request can take down
all requests. So maybe its worth experimenting with it?

== 8:< ==

  #include <stdio.h>
  #include <pthread.h>

  static void pthread_get_stack(void **stack_begin, void **stack_end) {
          size_t stack_size;
  #if defined(HAVE_STACKADDR_NP) && defined(HAVE_GET_STACKSIZE_NP) /* MacOS X */
          pthread_t t_id = pthread_self();
          *stack_begin = pthread_get_stackaddr_np(t_id);
          stack_size = pthread_get_stacksize_np(t_id);
  #else /* Linux */
          pthread_attr_t attr;
          pthread_getattr_np(pthread_self(), &attr);
          pthread_attr_getstack(&attr, stack_begin, &stack_size);
  #endif
          *stack_end = *stack_begin + stack_size;
  }

  static void * last = 0;

  void rec_to_death(int i)
  {
    void *start;
    void *end;
    void *current = &current;
    pthread_get_stack(&start, &end);
    printf("is: %x between? %x start: %x next : %x, left: %d \n", current, current > start && current < end , start, current + (current - last), ((long int) current) - ((long int) start));
    last = current;
    rec_to_death(i+1);
  }

  int main(int argc, char * argv[])
  {
    rec_to_death(0);
  }

== 8:< ==

comments ?

Marc Weber



More information about the Ur mailing list