c – valgrind / helgrind在压力测试中被杀死

我正在使用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个).

>问题是否可能仅在运行时发生
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;
}

附:线程是:

>主线程.这里接受连接.
>一个帮助线程,它监听信号并发送信号.它会停止应用程序的信号接收并手动轮询信号队列.原因是因为使用线程时很难处理信号.我在stackoverflow中发现了这种技术,并且它在其他项目中工作得非常好.
>客户端连接线程

完整的代码非常大,但如果有人感兴趣,我可以发布块.

更新:

我设法只用一个连接触发问题.这一切都发生在客户端线程中.这就是我做的:

>我读/解析标题.我在写入之前放置了延迟,因此客户端可以超时(导致问题).
>这里客户端超时和离开(可能关闭套接字)
>我写回标题
>我回写了html代码.

这是我回信的方式

  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的所有信息.

点赞