Home > programming > 一个愚蠢的错误,inotify handle不可写

一个愚蠢的错误,inotify handle不可写

以前的同事的一个模块在程序退出的会卡住,也就是pthread_join不返回。于是检查其原因。发现这个模块是一个线程类,用于监视文件系统上的文件事件。该类并没有加入退出的逻辑。该类的run函数中使用read函数来获得文件系统的消息。为了能正常退出,我添加了一些退出的逻辑。大致如下

void FileEventMonitor::run()
{//这里是在一个新的线程中运行的
	while(!mbQuit)
	{
		int r = read( inotifyHandle , buffer, buffersize );
		if( this->bQuit) //增加了判断,如果要退出的话就break
			break;
		/process the event
	}
}
void FileEventMonitor::stop()
{
	bQuit = true;
	write(inotifyHandle,"q",1);
	pthread_join();//等待线程退出
}

我天真的以为直接想inotifyHandle中写入一点数据,read函数就可以退出,然后由于bQuit被置成了true,那么线程就会退出了。结果测试的时候发现还是退不出去,而我又没有判断write的返回值,所以一开始我一直认为是其他的什么怪异的原因。知道后来加上了对write返回值的判断才发现是写失败了。不过很是奇怪的是write失败后的errno是9,也就是bad file number。

  很明显,这条路走不通了,于是我在read之前加上了select,只有当有数据的时候才去read,并且加上一个timeout时间,例如500ms(这样的话service退出也不会等待太久)。这样就解决了这个无法正常退出的问题。

代码如下:

void FileEventMonitor::monitor()
{
    fd_set fds;
    struct timeval tv;
    while(!mbQuit)
    {
        tv.tv_sec = 0;
        tv.tv_usec = 5000 * 1000; //500ms
        FD_ZERO(&fds);
        FD_SET(mEventhandle,&fds);
        int r = select( mEventhandle + 1 , &fds, NULL , NULL , &tv);
        if( r < 0)
        {
            //log error
            break
        }
        else if( r == 0 )
        {
            continue;
        }
	//process the event
    }
}

在stop函数中只需要简单的吧mbQuit置成true就可以了。

不过我现在还有点疑问,既然write的时候返回bad file number,那么为何可以使用select来检测这个handle上是否有数据可读,select不也是操作文件描述符的吗?有点不太懂。

   不过,至少退出的问题是解决了。今天记录一下这个问题,希望以后不要想当然的认为某个调用就一定会成功。

Categories: programming Tags:
  1. No comments yet.
  1. No trackbacks yet.