我正在使用pthread在C++的Linux上制作Web服务器。我用valgrind测试了它的泄漏和内存问题-都已修复。我用helgrind测试了它的线程问题-全部修复。我正在尝试stress test。用Helgrind运行亵渎时我遇到问题
valgrind --tool=helgrind ./chats
它只是在随机的地方死于文本“Killed”,就像我用
kill -9
杀死它一样。我有时从helgrind那里获得的唯一报告是,该程序存在,同时还持有一些锁,这在被杀死时很正常。检查泄漏时:
valgrind --leak-check=full ./chats
它更稳定,但我设法通过数百个并发连接使其一次消失。
我尝试单独运行程序,根本无法使其崩溃。我尝试了250个并发连接。每个线程延迟100毫秒,以使同时进行多个连接变得更容易。没有崩溃。
在所有情况下,线程和连接都不会超过10,即使有2个连接,它也崩溃,但绝不会同时只有1个连接(包括主线程和1个辅助线程的总数为3)。
helgrind还是仅仅helgrind使其更可能显示?
我进行了更多测试,发现它仅在客户端超时并关闭连接时消失。因此,这是检测客户端关闭套接字的代码:
void *TcpClient::run(){
int ret;
struct timeval tv;
char * buff = (char *)malloc(10001);
int br;
colorPrintf(TC_GREEN, "new client starting: %d\n", sockFd);
while(isRunning()){
tv.tv_sec = 0;
tv.tv_usec = 500*1000;
FD_SET(sockFd, &readFds);
ret = select(sockFd+1, &readFds, NULL, NULL, &tv);
if(ret < 0){
//select error
continue;
}else if(ret == 0){
// no data to read
continue;
}
br = read(sockFd, buff, 10000);
buff[br] = 0;
if (br == 0){
// client disconnected;
setRunning(false);
break;
}
if (reader != NULL){
reader->tcpRead(this, std::string(buff, br));
}else{
readBuffer.append(buff, br);
}
//printf("received: %s\n", buff);
}
free(buff);
sendFeedback((void *)1);
colorPrintf(TC_RED, "closing client socket: %d\n", sockFd);
::close(sockFd);
sockFd = -1;
return NULL;
}
// this method writes to socket
bool TcpClient::write(std::string data){
int bw;
int dataLen = data.length();
bw = ::write(sockFd, data.data(), dataLen);
if (bw != dataLen){
return false; // I don't close the socket in this case, maybe I should
}
return true;
}
P.S.线程是:
完整的代码很大,但是如果有人感兴趣,我可以发布代码块。
更新:
我仅用一个连接就触发了该问题。这一切都发生在客户端线程中。这是我的工作:
这是我回信的方式
bw = ::write(sockFd, data.data(), dataLen);
// bw is = dataLen = 108 when writing the headers
//then secondary write for HTML kills the program. there is a message before and after write()
bw = ::write(sockFd, data.data(), dataLen); // doesn't go past this point second time
更新2:知道了:)
gdb sais:
Program received signal SIGPIPE, Broken pipe.
[Switching to Thread 0x41401940 (LWP 10554)]
0x0000003ac2e0d89b in write () from /lib64/libpthread.so.0
问题1:我应该怎么做才能使收到此信号无效。
问题2:如何知道写入时远端已断开连接。选择读取时返回有数据,但读取的数据为0。写操作如何?
最佳答案
好吧,我只需要处理SIGPIPE信号并写返回-1->我关闭套接字并优雅地退出线程。奇迹般有效。
我猜最简单的方法是将SIGPIPE的信号处理程序设置为SIG_IGN:
signal(SIGPIPE, SIG_IGN);
请注意,首次写入成功,并且没有终止程序。如果您有类似的问题,请检查是否要编写一次或多次。如果您不熟悉gdb,请执行以下操作:
gdb ./your-program
> run
并且gdb会告诉您有关信号和sigfaults的所有信息。