远行的心 发表于 2015-9-10 11:07:35

MooseFS源代码中的一个bug

学习分布式文件系统时,曾经download了moosefs的源代码,做了简单的测试,发现moose的实现效率还不错,在阅读器源代码时,发现了其封装了C socket接口,于是把相关的文件保存下来了。昨天闲着没事,想测试一下这个socket接口,在测试udp时,发现服务器接收到数据后,不能正确的向客户端返回信息。

阅读了代码发现问题在udpread函数上,udpread的实现如下:

int udpread(int sock,uint32_t addr,void *buff,uint16_t leng)
{
         if (addr>addrlen) return -1;
         if (addr==0xffffffff) { // ignore peer name
                   return recvfrom(sock,buff,leng,0,(struct sockaddr *)NULL,0);
         } else {
                   socklen_t templeng;
                   struct sockaddr tempaddr;
                   return recvfrom(sock,buff,leng,0,&tempaddr,&templeng);

                   if (templeng==sizeof(struct sockaddr_in)) {
                            addrtab = *((struct sockaddr_in*)&tempaddr);
                   }
         }
}

第1、3、4个参数很容易理解,第二个参数是一个地址池的编号,这个socket实现中,将经常用到的struct sockaddr结构放到一个内存池(addrtab)中,需要该结构时,直接从内存池中取,并返回地址在地址池中的编号。

第二个参数addr即为地址池中一个struct sockaddr的编号,将该编号传入,udpread将另一端的地址填充到对应编号的sockaddr结构中。但此版本的udpread实现中,recvfrom执行完后就直接return了,后面的填充步骤并没有进行,我做了修改后,udp服务器运行正常。

本来想把这个问题report个moosefs的作者的,下了新版的源代码(mfs-1.6.15),发现该bug已经修正,修正后的代码为:

int udpread(int sock,uint32_t *ip,uint16_t *port,void *buff,uint16_t leng) {
         socklen_t templeng;
         struct sockaddr tempaddr;
         struct sockaddr_in *saptr;
         int ret;
         ret = recvfrom(sock,buff,leng,0,&tempaddr,&templeng);
         if (templeng==sizeof(struct sockaddr_in)) {
                   saptr = ((struct sockaddr_in*)&tempaddr);
                   if (ip!=(void *)0) {
                            *ip = ntohl(saptr->sin_addr.s_addr);
                   }
                   if (port!=(void *)0) {
                            *port = ntohs(saptr->sin_port);
                   }
         }
         return ret;
}

对于网络上的资源(原理讲解,源代码),一定要抱着怀疑的态度看待,否则接受了错误的知识自己去还不知道,尽信书不如无书,自己悟到的才是最好的。
页: [1]
查看完整版本: MooseFS源代码中的一个bug