我遇到了valgrind和select的问题。当我在终端中运行我的应用程序或当我使用gdb运行我的应用程序时,我没有错误。一切都运行良好,如预期的那样。
当我使用valgrind运行我的应用程序时,我收到以下错误:
valgrind --tool=memcheck --leak-check=full ./myservice
==3403== Thread 12:
==3403== Syscall param select(readfds) points to uninitialised byte(s)
==3403== at 0x41C3E31: ??? (syscall-template.S:81)
==3403== by 0x805531B: myThread (myservice.c:2062)
==3403== by 0x40CAF6F: start_thread (pthread_create.c:312)
==3403== by 0x41CBBED: clone (clone.S:129)
==3403== Address 0xf5c9f38 is on thread 12's stack
==3403==
我的应用程序本身将打印出以下错误:
Sep 15, 2015 | 10:30:32 | select: Bad file descriptor
我对valgrind很新,所以我不了解valgrind正在做什么来打破选择。相关代码粘贴在下面。
Global Pipe
int pipefd[2];
中断处理程序
void intHandler(int sig) {
keepRunning = false;
write(pipefd[1], "terminate", sizeof("terminate"));
}
主要
int main(int argc, char *argv[]){
int i = 0;
...
signal(SIGINT, intHandler);
pipe(pipefd);
...
pthread_t myThreadHandle[10];
for (i = 0; i < 10; i++) {
pthread_create(&myThreadHandle[i], NULL, myThread, NULL);
}
...
}
我的主题
void *myThread(void *ptr) {
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
...
int socketfd = 555; //edit: forgot to include socketfd code, this is the error
...
fd_set readfs;
FD_ZERO(&readfs);
FD_SET(pipefd[0], &readfs);
if(select(socketfd+1, &readfs, NULL, NULL, &tv) < 0){ //ln 2062
snprintf(logMessage, sizeof(logMessage),"select: %s", strerror(errno));
writeLog(logMessage);
}
...
}
基本上我想优雅地终止我的应用程序。我在main中初始化管道,并使用管道来监视select语句。如果不写入管道,选择将处于空闲状态直到超时。我使用信号处理程序写入管道,因此我的select语句将知道管道已写入并停止等待。
我是如何为多个线程使用一个管道的问题?根据我的理解,select实际上并没有触及数据,只看到它在那里。因此每个线程应该看到管道上的数据,修改自己的fd_set并在超时之前退出select(这与我在gdb中看到的一致)。
修复(编辑) - 使用错误的nfds值进行选择,使用readfs中的pipefd进行更正。
if(select(pipefd[0]+1, &readfs, NULL, NULL, &tv) < 0){ //ln 2062