c++ - Why is opendir() randomly resulting in ENOENT? -
to retrieve contents of directory (recursively) on linux ubuntu, i'm using following raii struct:
struct l_directoryreader { //fields l_pathdata pathdata; dir *dirhandle; struct dirent *currentdirentry; //method declaration happens before constructor, //because used in constructor. void readdir() { errno = 0; this->currentdirentry = readdir(this->dirhandle); //error checking if(errno != 0) { int errorcode = errno; switch(errorcode) { default: { throw os3util::fileh::exc::fileioexception( std::string("failed retrieve contents of dir:") + knewline_str + this->pathdata.relativepath.getfullpath() + knewline_str + "with readdir() errorcode " + os3util::strfunc::inttostring(errorcode) + std::string(".") ); } } } } //constructor l_directoryreader(const l_pathdata& pathdata) : pathdata(pathdata), dirhandle(), currentdirentry() { //obtain file handle const char* opendirpathcstring = (kslash_str + this->pathdata.absolutepath.getfullpath()).c_str(); errno = 0; this->dirhandle = opendir(opendirpathcstring); //check file handle validity if(this->dirhandle == nullptr) { int errorcode = errno; switch(errorcode) { case eacces: { throw os3util::fileh::exc::fileioexception(std::string("could not find directory:") + knewline_str + this->pathdata.relativepath.getfullpath() + knewline_str + std::string("permission denied.")); } break; case enoent: { throw os3util::fileh::exc::fileioexception(std::string("could not find directory:") + knewline_str + this->pathdata.relativepath.getfullpath() + knewline_str + std::string("does not exist.")); } break; case enotdir: { throw os3util::fileh::exc::fileioexception(std::string("could not find directory:") + knewline_str + this->pathdata.relativepath.getfullpath() + knewline_str + std::string("is not directory.")); } break; default: { throw os3util::fileh::exc::fileioexception(std::string("could not find directory:") + knewline_str + this->pathdata.relativepath.getfullpath() + knewline_str + std::string("error code ") + os3util::strfunc::inttostring(errorcode) + std::string(" received.")); } } } else { try { this->readdir(); } catch(...) { closedir(this->dirhandle); throw; } } } //destructor ~l_directoryreader() { try { errno = 0; closedir(this->dirhandle); if(errno != 0) { int errorcode = errno; std::cout << "failed close dirhandle directory \"" << this->pathdata.relativepath.getfullpath() << "\" error code " << errorcode << std::endl; } } catch(...) { try { std::cout << "exception occured while closing dir handle" << std::endl; } catch(...) { /*swallow, destructors should never throw*/ } } } };
the problem is, keep getting exception enoent
. not always. (manually) call on , on again same directory , prints contents (and subdirectory contents) intended , throws exception. first call succeeds, first call fails. don't directories @ all, stay in same place, untouched.
other topics similar issue i've found involved not setting errno
0, code above shows, i'm doing that. i'm constructing const char *
parameter before setting errno
0, in case.
the struct constructed inside function. if exception throws, destructor activates , closes dir
handle. debugging confirms this. error messages in destructor never happen. thing go wrong there dirhandle
null, , constructor fails in scenario.
when disable recursion, works root dir, fails of root dir's subdirectories. root directory home/myname/os3/serverfiles
. project in different directory access absolute path.
every time struct accessed through exact same function calls. there no random factor in program anywhere.
i'm out of ideas cause this. i'm puzzled error enoent
when files exist , finds them.
const char* opendirpathcstring = (kslash_str + this->pathdata.absolutepath.getfullpath()).c_str();
you calling string::c_str()
on temporary string destroyed @ end of statement, resulting in dangling pointer.
Comments
Post a Comment