我一直在Raspberry pi上使用C进行修补,我的main()旋转了几个线程,其中一个线程中运行着一个小型Web服务器,
int main(){
printf("hello world\n");
thisfn();
pthread_t tid, led_tid;
int port = 9193;
int rc = pthread_create(&tid, NULL, webserver, &port);
assert (rc == 0);
/snip
如果Web服务器无法绑定到所需的端口,我希望整个程序停止。
void *webserver(void *vargp){
int *port = (int *) vargp;
printf("our port is %d\n", *port);
/* First: Socket Creation */
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
/* On error, -1 is returned */
perror("Server Error!");
abort();
} else {
printf("sockfd is %d\n", sockfd);
}
printf("Socket: sockfd: %d\n", sockfd);
/* Second: Set socket options */
int optval = 1;
//int sockopt_int = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &optval, sizeof(optval) );
int sockopt_int = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR , &optval, sizeof(optval) );
if ( sockopt_int < 0 ){
perror("Failed at setsockopt");
abort();
} else {
printf("setsockopt succeeded\n");
}
/* Third: Bind to the port */
/* int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); */
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(*port);
int bind_int = bind(sockfd, (struct sockaddr *)&address, sizeof(address)) ;
printf("bind_int ; %d\n", bind_int);
if (bind_int < 0 ) {
perror("Failed at bind");
abort();
} else {
printf("bind succeeded\n");
}
我一直在调用abort(),我也尝试过exit(1),_ exit(1)等-但是,这样做在我用valgrind检查时会泄漏内存(〜136字节)。
==13052== 136 bytes in 1 blocks are possibly lost in loss record 1 of 1
==13052== at 0x4849CE0: calloc (vg_replace_malloc.c:711)
==13052== by 0x401379B: allocate_dtv (dl-tls.c:322)
==13052== by 0x40141D3: _dl_allocate_tls (dl-tls.c:539)
==13052== by 0x489D9EF: allocate_stack (allocatestack.c:580)
==13052== by 0x489D9EF: pthread_create@@GLIBC_2.4 (pthread_create.c:539)
==13052== by 0x10EBF: main (fixmem.c:38)
==13052==
==13052== LEAK SUMMARY:
==13052== definitely lost: 0 bytes in 0 blocks
==13052== indirectly lost: 0 bytes in 0 blocks
==13052== possibly lost: 136 bytes in 1 blocks
==13052== still reachable: 0 bytes in 0 blocks
==13052== suppressed: 0 bytes in 0 blocks
==13052==
我了解到有种学问,当有东西砸到风扇上时,可以退出系统,然后允许操作系统进行清理。我试图用更快乐的valgrind使其退出/中止。我没有在此函数中执行任何显式的mallocs / callocs来在abort()之前调用free(),这引起了我的问题:
从线程停止主线程和退出线程的最干净方法是什么?
谢谢!
答案 0 :(得分:1)
如果Web服务器无法绑定到所需的端口,我希望整个程序停止。
如果您希望整个程序停止运行,则可以调用_exit()
-就是这样。
忽略valgrind报告的“泄漏”,它们是由于清理代码没有机会运行而造成的误报。由于操作系统会回收属于已退出进程的所有内存(和其他资源),因此实际上不会泄漏任何内存。
答案 1 :(得分:0)
我怀疑,如果成功创建了Web服务器并且线程正常退出,则不会发生内存泄漏,对吗?如果是这样,则主线程可能在退出之前有一些资源需要清理(似乎pthread_create会分配一些内存)。
因此,我建议您建立信号处理程序并适当终止主线程。函数abort()
发送信号进行处理。因此,您可以创建信号处理程序以在主线程中捕获此类信号并进行清理。 Here是一个很好的例子。在示例中,SIGTERM被连接,原子变量done
设置为1。在主循环中定期检查此变量,并且在终止1个程序的情况下。在终止之前,您可以停止Web服务器线程并释放在pthread_create中分配的内存。
({abort()
发送SIGABRT,因此您必须从示例中更改代码)
其他想法:
在主线程中使用pthread_join
来监视Web服务器线程退出代码。在Web服务器线程中,调用pthread_exit
以通知主线程错误并允许正常终止。考虑到,pthread_join将阻塞您的主线程。但是最好从main创建多个工作线程,然后一个一个地加入它们。
使用Mutex / Conditional变量将错误通知主线程。 Web服务器线程将这种条件变量设置为某些错误代码,并以return
退出。主线程将监视条件变量,并在发生错误的情况下终止程序。