Fix Folder as Workspace crash and "queue overflow" issues
Fix crash of Folder as Workspace when too many directory changes happen: Remove limit for amount of queued directory changes: use auto-reset Event instead of Semaphore. Fix #6005, fix #5907, fix #3740, close #6005
This commit is contained in:
parent
9d79d6c017
commit
ab4cf88336
@ -39,7 +39,6 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params)
|
||||
{
|
||||
MonitorInfo *monitorInfo = static_cast<MonitorInfo *>(params);
|
||||
@ -76,14 +75,12 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params)
|
||||
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
// We've received a notification in the queue.
|
||||
{
|
||||
if (changes.CheckOverflow())
|
||||
printStr(L"Queue overflowed.");
|
||||
else
|
||||
{
|
||||
DWORD dwAction;
|
||||
CStringW wstrFilename;
|
||||
changes.Pop(dwAction, wstrFilename);
|
||||
// Process all available changes, ignore User actions
|
||||
while (changes.Pop(dwAction, wstrFilename))
|
||||
{
|
||||
generic_string fn = wstrFilename.GetString();
|
||||
|
||||
// Fix monitoring files which are under root problem
|
||||
|
@ -1354,11 +1354,9 @@ DWORD WINAPI FolderUpdater::watching(void *params)
|
||||
{
|
||||
DWORD dwAction;
|
||||
CStringW wstrFilename;
|
||||
if (changes.CheckOverflow())
|
||||
printStr(L"Queue overflowed.");
|
||||
else
|
||||
// Process all available changes, ignore User actions
|
||||
while (changes.Pop(dwAction, wstrFilename))
|
||||
{
|
||||
changes.Pop(dwAction, wstrFilename);
|
||||
static generic_string oldName;
|
||||
static std::vector<generic_string> file2Change;
|
||||
file2Change.clear();
|
||||
|
@ -34,8 +34,8 @@ using namespace ReadDirectoryChangesPrivate;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CReadDirectoryChanges
|
||||
|
||||
CReadDirectoryChanges::CReadDirectoryChanges(int nMaxCount)
|
||||
: m_Notifications(nMaxCount)
|
||||
CReadDirectoryChanges::CReadDirectoryChanges()
|
||||
: m_Notifications()
|
||||
{
|
||||
m_hThread = NULL;
|
||||
m_dwThreadId= 0;
|
||||
@ -102,11 +102,3 @@ bool CReadDirectoryChanges::Pop(DWORD& dwAction, CStringW& wstrFilename)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CReadDirectoryChanges::CheckOverflow()
|
||||
{
|
||||
bool b = m_Notifications.overflow();
|
||||
if (b)
|
||||
m_Notifications.clear();
|
||||
return b;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ namespace ReadDirectoryChangesPrivate
|
||||
/// {
|
||||
/// DWORD dwAction;
|
||||
/// CStringW wstrFilename;
|
||||
/// changes.Pop(dwAction, wstrFilename);
|
||||
/// while (changes.Pop(dwAction, wstrFilename))
|
||||
/// wprintf(L"%s %s\n", ExplainAction(dwAction), wstrFilename);
|
||||
/// }
|
||||
/// break;
|
||||
@ -116,7 +116,7 @@ namespace ReadDirectoryChangesPrivate
|
||||
class CReadDirectoryChanges
|
||||
{
|
||||
public:
|
||||
CReadDirectoryChanges(int nMaxChanges=1000);
|
||||
CReadDirectoryChanges();
|
||||
~CReadDirectoryChanges();
|
||||
|
||||
void Init();
|
||||
@ -148,9 +148,6 @@ public:
|
||||
// "Push" is for usage by ReadChangesRequest. Not intended for external usage.
|
||||
void Push(DWORD dwAction, CStringW& wstrFilename);
|
||||
|
||||
// Check if the queue overflowed. If so, clear it and return true.
|
||||
bool CheckOverflow();
|
||||
|
||||
unsigned int GetThreadId() { return m_dwThreadId; }
|
||||
|
||||
protected:
|
||||
|
@ -123,11 +123,8 @@ VOID CALLBACK CReadChangesRequest::NotificationCompletion(
|
||||
|
||||
// Can't use sizeof(FILE_NOTIFY_INFORMATION) because
|
||||
// the structure is padded to 16 bytes.
|
||||
_ASSERTE(dwNumberOfBytesTransfered >= offsetof(FILE_NOTIFY_INFORMATION, FileName) + sizeof(WCHAR));
|
||||
|
||||
// This might mean overflow? Not sure.
|
||||
if (!dwNumberOfBytesTransfered)
|
||||
return;
|
||||
_ASSERTE((dwNumberOfBytesTransfered == 0) ||
|
||||
(dwNumberOfBytesTransfered >= offsetof(FILE_NOTIFY_INFORMATION, FileName) + sizeof(WCHAR)));
|
||||
|
||||
pBlock->BackupBuffer(dwNumberOfBytesTransfered);
|
||||
|
||||
|
@ -32,52 +32,35 @@ template <typename C>
|
||||
class CThreadSafeQueue : protected std::list<C>
|
||||
{
|
||||
public:
|
||||
CThreadSafeQueue(int nMaxCount)
|
||||
CThreadSafeQueue()
|
||||
{
|
||||
m_bOverflow = false;
|
||||
|
||||
m_hSemaphore = ::CreateSemaphore(
|
||||
m_hEvent = ::CreateEvent(
|
||||
NULL, // no security attributes
|
||||
0, // initial count
|
||||
nMaxCount, // max count
|
||||
FALSE, // auto reset
|
||||
FALSE, // non-signalled
|
||||
NULL); // anonymous
|
||||
}
|
||||
|
||||
~CThreadSafeQueue()
|
||||
{
|
||||
::CloseHandle(m_hSemaphore);
|
||||
m_hSemaphore = NULL;
|
||||
::CloseHandle(m_hEvent);
|
||||
m_hEvent = NULL;
|
||||
}
|
||||
|
||||
void push(C& c)
|
||||
{
|
||||
CComCritSecLock<CComAutoCriticalSection> lock( m_Crit, true );
|
||||
push_back( c );
|
||||
lock.Unlock();
|
||||
|
||||
if (!::ReleaseSemaphore(m_hSemaphore, 1, NULL))
|
||||
{
|
||||
// If the semaphore is full, then take back the entry.
|
||||
lock.Lock();
|
||||
pop_back();
|
||||
if (GetLastError() == ERROR_TOO_MANY_POSTS)
|
||||
{
|
||||
m_bOverflow = true;
|
||||
}
|
||||
CComCritSecLock<CComAutoCriticalSection> lock(m_Crit, true);
|
||||
push_back(c);
|
||||
}
|
||||
::SetEvent(m_hEvent);
|
||||
}
|
||||
|
||||
bool pop(C& c)
|
||||
{
|
||||
CComCritSecLock<CComAutoCriticalSection> lock( m_Crit, true );
|
||||
|
||||
// If the user calls pop() more than once after the
|
||||
// semaphore is signaled, then the semaphore count will
|
||||
// get out of sync. We fix that when the queue empties.
|
||||
if (empty())
|
||||
{
|
||||
while (::WaitForSingleObject(m_hSemaphore, 0) != WAIT_TIMEOUT)
|
||||
1;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -87,30 +70,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
// If overflow, use this to clear the queue.
|
||||
void clear()
|
||||
{
|
||||
CComCritSecLock<CComAutoCriticalSection> lock( m_Crit, true );
|
||||
|
||||
for (DWORD i=0; i<size(); i++)
|
||||
WaitForSingleObject(m_hSemaphore, 0);
|
||||
|
||||
__super::clear();
|
||||
|
||||
m_bOverflow = false;
|
||||
}
|
||||
|
||||
bool overflow()
|
||||
{
|
||||
return m_bOverflow;
|
||||
}
|
||||
|
||||
HANDLE GetWaitHandle() { return m_hSemaphore; }
|
||||
HANDLE GetWaitHandle() { return m_hEvent; }
|
||||
|
||||
protected:
|
||||
HANDLE m_hSemaphore;
|
||||
HANDLE m_hEvent;
|
||||
|
||||
CComAutoCriticalSection m_Crit;
|
||||
|
||||
bool m_bOverflow;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user