我正在使用pthreads在C ++上使用Linux创建一个Web服务器。我用valgrind测试了泄漏和内存问题 - 所有修复。我用helgrind测试了线程问题 - 所有修复。我正在尝试stress test。当使用helgrind
运行probram时,我遇到了问题valgrind --tool=helgrind ./chats
它只是在随机地方死亡,文字“被杀”,就像用kill -9
杀死它时一样。我有时从helgrind获得的唯一报告是程序存在时仍保留一些锁,这在被杀时是正常的。
检查泄漏时:
valgrind --leak-check=full ./chats
它更稳定,但我设法让它在几百个并发连接中死掉一次。
我尝试单独运行程序,但根本无法使其崩溃。我尝试了多达250个并发连接。每个线程延迟100毫秒,以便更容易同时拥有多个连接。没有崩溃。
在所有情况下,线程和连接都不会超过10并且我看到即使有2个连接它也会崩溃,但是从来没有同时只有一个连接(包括主线程和一个帮助线程总共3个)
我测试了一点,我发现它只会在客户端超时并关闭连接时死掉。所以这里是检测客户端关闭套接字的代码:
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.如何写?
答案 0 :(得分:2)
好吧,我只需处理SIGPIPE信号并写入返回-1 - &gt;我关闭套接字并优雅地退出线程。像魅力一样。
我想最简单的方法是将SIGPIPE的信号处理程序设置为SIG_IGN:
signal(SIGPIPE, SIG_IGN);
请注意,第一次写入是成功的,并没有杀死该程序。如果您有类似的问题,请检查您是写一次还是多次。如果你不熟悉gdb,那么这是怎么做的:
gdb ./your-program
> run
和gdb会告诉你有关信号和sigfaults的所有信息。