寫一套程序,WebService的用了Thrift,還有一個單機版。單機版運行一直正常,Thrift版卻總Crash在一個功能類的一個成員函數上。注意,是成員函數上,而不是成員函數裏。但在GDB的調試過程中,運行無比正常,用GDB調試Core就顯示在了該函數上。
出錯原因是在運行時編譯器發現函數中對棧空間的使用它搞不定了,就是太大了,於是在進入函數前就Crash掉了。
於是縮小了該函數中對棧的空間使用,正常通過。
也嘗試了用各種方式來增加程序對棧的使用上限。
1. 用ulimit -s 查看大小,但用ulimit -s 40960等增加也並不管用。
2. 看一個帖子:http://zjf30366.blog.163.com/blog/static/4111645820117453719575/
用這樣的程序來修改線程棧大小:
void *stackaddr;
size_t stacksize;
size_t guardsize;
pthread_attr_t attr;
if (pthread_attr_init(&attr) != 0){
printf("init attr failed.\n");
return -1;
}
if (pthread_attr_getstacksize(&attr,&stacksize) == 0){
printf("default stacksize:0x%x\n",stacksize);
}
if (pthread_attr_getstack(&attr,&stackaddr,&stacksize) == 0){
printf("default stacksize:0x%x,stack addr:%p\n",stacksize,stackaddr);
}
if (pthread_attr_getguardsize(&attr,&guardsize) == 0){
printf("default guardsize:%u\n",guardsize);
}
stacksize = 40960;
if (pthread_attr_setstacksize(&attr,stacksize) != 0){
printf("set thread stack size failed,error:%s\n",strerror(errno));
return -1;
}
printf("-----------\n");
if (pthread_attr_getstack(&attr,&stackaddr,&stacksize) == 0){
printf("after set stacksize,stacksize:0x%x,stack addr:%p\n",stacksize,stackaddr);
}
if (pthread_attr_setstack(&attr,(void *)0x80000,stacksize) != 0){
printf("set stack error:%s\n",strerror(errno));
}
if (pthread_attr_getguardsize(&attr,&guardsize) == 0){
printf("after set stack,guardsize:%u\n",guardsize);
}
if (pthread_attr_getstack(&attr,&stackaddr,&stacksize) == 0){
printf("after setstack,stacksize:0x%x,stack addr:%p\n",stacksize,stackaddr);
}
printf("-----------\n");
if (pthread_attr_getstacksize(&attr,&stacksize) == 0){
printf("default stacksize:0x%x\n",stacksize);
}
if (pthread_attr_getstack(&attr,&stackaddr,&stacksize) == 0){
printf("default stacksize:0x%x,stack addr:%p\n",stacksize,stackaddr);
}
if (pthread_attr_getguardsize(&attr,&guardsize) == 0){
printf("default guardsize:%u\n",guardsize);
}
也並不管用。
3. 用Thrift的PosixThreadFactory類中的void setStackSize(int value)函數來設置線程棧大小,該問題得以解決。
我是用的Thrift中非阻塞的方式:
threadManager = ThreadManager::newSimpleThreadManager(100);
shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
int nStackSize = threadFactory->getStackSize();
printf("1:stack size:%d\n", nStackSize); // default value is 1
threadFactory->setStackSize(10);
nStackSize = threadFactory->getStackSize();
printf("2:stack size:%d\n", nStackSize);
threadManager->threadFactory(threadFactory);
threadManager->start();
總結:
單機版運行無誤,Thrift版運行Crash,是因爲函數中除了自身需要的,Thrift也會佔去一部分,而且不好用系統的系統的線程棧函數來修改,而用Thrift自已的接口函數來修改。
爲求保險還是應該縮小函數中對棧空間的使用。