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[addr] = *((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;
}
对于网络上的资源(原理讲解,源代码),一定要抱着怀疑的态度看待,否则接受了错误的知识自己去还不知道,尽信书不如无书,自己悟到的才是最好的。