mirror of
https://github.com/vgough/encfs.git
synced 2024-11-21 23:43:26 +01:00
eraseNode: erase the right FileNode
When a file is opened twice concurrently, we can end up with two separate FileNodes for a single path. This seems to be the root cause for the crashes reported under https://github.com/vgough/encfs/issues/214 , as commitaf64702dd0
"Simplify FileNode Cache. Remove the need for PlaceHolder." removed the awareness for different FileNodes. The crashes have been fixed bye2f0f8e3c6
"fuseFhMap: translate FUSE file handles to FileNode pointers" at the cost of introducing a memory leak. One of the two FileNodes would stay in fuseFhMap forever. This commit makes eraseNode again aware of different FileNodes for a single path, makes sure the right FileNode is erased, and fixes the memory leak.
This commit is contained in:
parent
e2f0f8e3c6
commit
9ed8d704dd
@ -89,7 +89,7 @@ std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
|
||||
|
||||
FileMap::iterator it = openFiles.find(std::string(path));
|
||||
if (it != openFiles.end()) {
|
||||
// all the items in the set point to the same node.. so just use the
|
||||
// every entry in the list is fine... so just use the
|
||||
// first
|
||||
return it->second.front();
|
||||
}
|
||||
@ -125,16 +125,25 @@ void EncFS_Context::eraseNode(const char *path, std::shared_ptr<FileNode> fnode)
|
||||
|
||||
FileMap::iterator it = openFiles.find(std::string(path));
|
||||
rAssert(it != openFiles.end());
|
||||
auto &list = it->second;
|
||||
|
||||
auto fn = it->second.front();
|
||||
// Find "fnode" in the list of FileNodes registered under this path.
|
||||
auto findIter = std::find(list.begin(), list.end(), fnode);
|
||||
rAssert(findIter != list.end());
|
||||
list.erase(findIter);
|
||||
|
||||
it->second.pop_front();
|
||||
// If no reference to "fnode" remains, drop the entry from fuseFhMap
|
||||
// and overwrite the canary.
|
||||
findIter = std::find(list.begin(), list.end(), fnode);
|
||||
if (findIter == list.end()) {
|
||||
fuseFhMap.erase(fnode->fuseFh);
|
||||
fnode->canary = CANARY_RELEASED;
|
||||
}
|
||||
|
||||
// if no more references to this file, remove the record all together
|
||||
if (it->second.empty()) {
|
||||
fn->canary = CANARY_RELEASED;
|
||||
// If no FileNode is registered at this path anymore, drop the entry
|
||||
// from openFiles.
|
||||
if (list.empty()) {
|
||||
openFiles.erase(it);
|
||||
fuseFhMap.erase(fn->fuseFh);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,8 @@
|
||||
#ifndef _Context_incl_
|
||||
#define _Context_incl_
|
||||
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <pthread.h>
|
||||
#include <set>
|
||||
@ -85,7 +86,7 @@ class EncFS_Context {
|
||||
*/
|
||||
|
||||
typedef std::unordered_map<std::string,
|
||||
std::forward_list<std::shared_ptr<FileNode>>>
|
||||
std::list<std::shared_ptr<FileNode>>>
|
||||
FileMap;
|
||||
|
||||
mutable pthread_mutex_t contextMutex;
|
||||
|
Loading…
Reference in New Issue
Block a user