forked from Mirrors/privacore-open-source-search-engine
Synchronize File::open() and File::close()
Multiple threads could call File::open() for the same instance and end up leaking file descriptors. Mutex added to open/close. This doesn't solve all race conditions but should prevent the most frequent ones. bigfile/merge still calls close1_r/close2/getfd directly so those race conditions 8although presumably rare) are still possible.
This commit is contained in:
19
File.cpp
19
File.cpp
@ -82,6 +82,8 @@ File::File ( ) {
|
||||
m_calledOpen = false;
|
||||
m_calledSet = false;
|
||||
|
||||
pthread_mutex_init(&m_mtxFdManipulation,NULL);
|
||||
|
||||
logDebug( g_conf.m_logDebugDisk, "disk: constructor fd %i this=0x%" PTRFMT, m_fd, (PTRTYPE)this );
|
||||
}
|
||||
|
||||
@ -94,6 +96,8 @@ File::~File ( ) {
|
||||
// set m_calledSet to false so BigFile.cpp see it as 'empty'
|
||||
m_calledSet = false;
|
||||
m_calledOpen = false;
|
||||
|
||||
pthread_mutex_destroy(&m_mtxFdManipulation);
|
||||
}
|
||||
|
||||
|
||||
@ -153,13 +157,19 @@ bool File::rename ( const char *newFilename ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// . open the file
|
||||
// . only call once per File after calling set()
|
||||
bool File::open ( int flags , int permissions ) {
|
||||
ScopedLock sl(m_mtxFdManipulation);
|
||||
return open_unlocked(flags,permissions);
|
||||
}
|
||||
|
||||
bool File::open_unlocked(int flags, int permissions) {
|
||||
// if we already had another file open then we must close it first.
|
||||
if ( m_fd >= 0 ) {
|
||||
log( LOG_LOGIC, "disk: Open already called. Closing and re-opening." );
|
||||
close();
|
||||
close_unlocked();
|
||||
}
|
||||
|
||||
// save these in case we need to reopen in getfd()
|
||||
@ -177,7 +187,7 @@ bool File::open ( int flags , int permissions ) {
|
||||
// . close the virtual fd so we can call open again
|
||||
// . sets s_fds [ m_vfd ] to -2 (available)
|
||||
// . and sets our m_vfd to -1
|
||||
close();
|
||||
close_unlocked();
|
||||
|
||||
// otherwise bitch and return false
|
||||
return false;
|
||||
@ -413,6 +423,11 @@ void File::close2_unlocked() {
|
||||
// . closes the file for real!
|
||||
// . analogous to a reset() routine
|
||||
bool File::close ( ) {
|
||||
ScopedLock sl(m_mtxFdManipulation);
|
||||
return close_unlocked();
|
||||
}
|
||||
|
||||
bool File::close_unlocked() {
|
||||
// return true if not open
|
||||
if ( m_fd < 0 ) return true;
|
||||
|
||||
|
6
File.h
6
File.h
@ -26,6 +26,8 @@
|
||||
#include "Mem.h" // for g_mem
|
||||
#include "Loop.h" // for g_loop.setNonBlocking(int fd)
|
||||
#include "SafeBuf.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
bool doesFileExist ( const char *filename ) ;
|
||||
|
||||
@ -170,6 +172,10 @@ private:
|
||||
char m_calledSet;
|
||||
|
||||
bool m_forceRename;
|
||||
|
||||
pthread_mutex_t m_mtxFdManipulation;
|
||||
bool open_unlocked(int flags, int permissions);
|
||||
bool close_unlocked();
|
||||
};
|
||||
|
||||
#endif // GB_FILE_H
|
||||
|
Reference in New Issue
Block a user