uClinux kernel panic: Stack overflow

Orange Pi Development Boards

If you’re using ucLinux, you may get kernel panic errors  coming out of nowhere. There may be several reasons (buffer overflow, out of memory..), but the most common is stack overflow for the process or one of the threads.

To increase the stack size of a flat binary you’ll need to adjust the LDFLAGS as follows:

LDFLAGS+=-Wl,-elf2flt=”-s65536″

This will set the stack size to 64KB.

To change the stack size of a thread (e.g. 32KB below), you’ll need to set the stack size attribute:

pthread_attr_init(&attr);
err = pthread_attr_setstacksize(&attr, 32*1024);
if (err) {
printf(“pthread_attr_setstacksize returned non-zero: %s\n”,
strerror(errno));
}
err = pthread_create(&pthThread, &attr, thread, NULL);

How to detect which thread suffers from stack overflow ?

First you can check your code for recursive function calls and local variables (especially arrays) both of which will be added at runtime to the stack to estimate what should be the stack size. So if you have large arrays you may use a pointer + a call to malloc instead.

If this can not fix the issue, you can use the  functions below to return the used and free stack size used by a particular thread.

uint32_t threadstack_free(pthread_t *thread)
{
pthread_handle handle = thread_handle(*thread);
pthread_descr  th = handle->h_descr;
uint32_t      *p;

for(p=(uint32_t*)handle->h_bottom;
((p<(uint32_t*)th) && (*p==0));
p++);

return (uint32_t)p – (uint32_t)handle->h_bottom;
}

uint32_t threadstack_used(pthread_t *thread)
{
pthread_handle handle = thread_handle(*thread);
pthread_descr  th = handle->h_descr;
uint32_t      *p;

for(p=(uint32_t*)handle->h_bottom;
((p<(uint32_t*)th) && (*p==0));
p++);

return (uint32_t)th – (uint32_t)p;
}

You can also download this code as a small library from  rowentel blog

On the platform we used (em8623L), this will only work the first time the thread is started, if the thread is restarted the data return by the functions above may not be correct since the memory allocated by the stack may not be set to zero.

To work around that issue, you’ll need to allocate the stack by yourself:

stack_addr = malloc(32*1024);
if(stack_addr == NULL) {
printf(“Failed to allocate video thread stack: %s”, strerror(errno));
return -1;
}
memset(stack_addr, 0, 32*1024);

err = pthread_attr_setstackaddr(&attr, stack_addr + 32*1024);
if (err) {
printf(“pthread_attr_setstackaddr returned non-zero: %s\n”, strerror(errno));
}

However, for whatever reason, allocating the stack by ourselves had proven to make our software unstable so we only used it for debugging purpose.

Support CNX Software - Donate via PayPal or become a Patron on Patreon

1
Leave a Reply

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
0 Comment authors
CNXSoft – Embedded Software Development » Embedded Software Books Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
trackback

[…] a focus on embedded systems (e.g. interrupts handling, real-time capabilities, volatile variables, processes and threads’ stack handling, , cross compilers…).  Programming Embedded Systems: With C and GNU Development Tools, 2nd […]