【发布时间】:2012-03-16 18:42:01
【问题描述】:
我的印象是flock(2)是线程安全的,我最近在代码中遇到了这样一个案例,多个线程能够在同一个文件上获得一个锁,这些都是同步使用获得独占使用 c api 群锁定。进程 25554 是具有 20 个线程的多线程应用程序,当死锁发生时,锁定同一文件的线程数会有所不同。多线程应用程序 testEvent 是文件的写入者,而推送是文件中的读取者。不幸的是,lsof 没有打印 LWP 值,所以我找不到持有锁的线程。当下面提到的情况发生时,进程和线程都被困在 flock 调用上,如 pid 25569 和 25554 上的 pstack 或 strace 调用所示。有关如何在 RHEL 4.x 中克服此问题的任何建议。
我想更新的一件事是,flock 并不总是行为不端,当消息的 tx 速率超过 2 mbps 时,我才遇到与 flock 的死锁问题,低于该 tx 速率的所有内容都是文件。当我增加向 150 发送消息,然后发生群发问题。
我只是想问一下你对flockfile c api的看法。
sudo lsof filename.txt
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
push 25569 root 11u REG 253.4 1079 49266853 filename.txt
testEvent 25554 root 27uW REG 253.4 1079 49266853 filename.txt
testEvent 25554 root 28uW REG 253.4 1079 49266853 filename.txt
testEvent 25554 root 29uW REG 253.4 1079 49266853 filename.txt
testEvent 25554 root 30uW REG 253.4 1079 49266853 filename.txt
将调用write_data_lib_func lib 函数的多线程测试程序。
void* sendMessage(void *arg) {
int* numOfMessagesPerSecond = (int*) arg;
std::cout <<" Executing p thread id " << pthread_self() << std::endl;
while(!terminateTest) {
Record *er1 = Record::create();
er1.setDate("some data");
for(int i = 0 ; i <=*numOfMessagesPerSecond ; i++){
ec = _write_data_lib_func(*er1);
if( ec != SUCCESS) {
std::cout << "write was not successful" << std::endl;
}
}
delete er1;
sleep(1);
}
return NULL;
上面的方法会在测试的main函数中的pthreads中被调用。
for (i=0; i<_numThreads ; ++i) {
rc = pthread_create(&threads[i], NULL, sendMessage, (void *)&_num_msgs);
assert(0 == rc);
}
这里是写入器/读取器源,由于专有原因,我不想只是剪切和粘贴,写入器源将在一个进程中访问多个线程
int write_data_lib_func(Record * rec) {
if(fd == -1 ) {
fd = open(fn,O_RDWR| O_CREAT | O_APPEND, 0666);
}
if ( fd >= 0 ) {
/* some code */
if( flock(fd, LOCK_EX) < 0 ) {
print "some error message";
}
else {
if( maxfilesize) {
off_t len = lseek ( fd,0,SEEK_END);
...
...
ftruncate( fd,0);
...
lseek(fd,0,SEEK_SET);
} /* end of max spool size */
if( writev(fd,rec) < 0 ) {
print "some error message" ;
}
if(flock(fd,LOCK_UN) < 0 ) {
print some error message;
}
在阅读器方面是一个没有线程的守护进程。
int readData() {
while(true) {
if( fd == -1 ) {
fd= open (filename,O_RDWR);
}
if( flock (fd, LOCK_EX) < 0 ) {
print "some error message";
break;
}
if( n = read(fd,readBuf,readBufSize)) < 0 ) {
print "some error message" ;
break;
}
if( off < n ) {
if ( off <= 0 && n > 0 ) {
corrupt_file = true;
}
if ( lseek(fd, off-n, SEEK_CUR) < 0 ) {
print "some error message";
}
if( corrupt_spool ) {
if (ftruncate(fd,0) < 0 ) {
print "some error message";
break;
}
}
}
if( flock(fd, LOCK_UN) < 0 )
print some error message ;
}
}
}
【问题讨论】:
-
能贴出调用
flock的代码吗? simple 测试程序会很好。 -
AFAIK,咨询锁不保证一致性。 gsp.com/cgi-bin/man.cgi?section=2&topic=flock