[SHELL32] CDirectoryWatcher: Check if window is alive (#6915)

Kill the zombie watchers for system
performance.
JIRA issue: CORE-13950
- Add HWND parameter to
  CDirectoryWatcher::Create.
- Check whether the HWND is alive at
  CDirectoryWatcher::IsDead.
This commit is contained in:
Katayama Hirofumi MZ 2024-05-22 20:33:26 +09:00 committed by GitHub
parent d7be7486c9
commit 8204c6e2fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 16 deletions

View file

@ -199,7 +199,8 @@ CreateDirectoryWatcherFromRegEntry(LPREGENTRY pRegEntry)
return NULL; return NULL;
// create a CDirectoryWatcher // create a CDirectoryWatcher
CDirectoryWatcher *pDirectoryWatcher = CDirectoryWatcher::Create(szPath, pRegEntry->fRecursive); CDirectoryWatcher *pDirectoryWatcher =
CDirectoryWatcher::Create(pRegEntry->hwnd, szPath, pRegEntry->fRecursive);
if (pDirectoryWatcher == NULL) if (pDirectoryWatcher == NULL)
return NULL; return NULL;

View file

@ -68,17 +68,18 @@ static void NTAPI _RequestAllTerminationAPC(ULONG_PTR Parameter)
s_hThreadAPC = NULL; s_hThreadAPC = NULL;
} }
CDirectoryWatcher::CDirectoryWatcher(LPCWSTR pszDirectoryPath, BOOL fSubTree) CDirectoryWatcher::CDirectoryWatcher(HWND hNotifyWnd, LPCWSTR pszDirectoryPath, BOOL fSubTree)
: m_fDead(FALSE) : m_hNotifyWnd(hNotifyWnd)
, m_fDead(FALSE)
, m_fRecursive(fSubTree) , m_fRecursive(fSubTree)
, m_dir_list(pszDirectoryPath, fSubTree) , m_dir_list(pszDirectoryPath, fSubTree)
{ {
TRACE("CDirectoryWatcher::CDirectoryWatcher: %p, '%S'\n", this, pszDirectoryPath); TRACE("%p, '%S'\n", this, pszDirectoryPath);
lstrcpynW(m_szDirectoryPath, pszDirectoryPath, MAX_PATH); GetFullPathNameW(pszDirectoryPath, _countof(m_szDirectoryPath), m_szDirectoryPath, NULL);
// open the directory to watch changes (for ReadDirectoryChangesW) // open the directory to watch changes (for ReadDirectoryChangesW)
m_hDirectory = CreateFileW(pszDirectoryPath, FILE_LIST_DIRECTORY, m_hDirectory = CreateFileW(m_szDirectoryPath, FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
@ -86,12 +87,10 @@ CDirectoryWatcher::CDirectoryWatcher(LPCWSTR pszDirectoryPath, BOOL fSubTree)
} }
/*static*/ CDirectoryWatcher * /*static*/ CDirectoryWatcher *
CDirectoryWatcher::Create(LPCWSTR pszDirectoryPath, BOOL fSubTree) CDirectoryWatcher::Create(HWND hNotifyWnd, LPCWSTR pszDirectoryPath, BOOL fSubTree)
{ {
WCHAR szFullPath[MAX_PATH]; CDirectoryWatcher *pDirectoryWatcher =
GetFullPathNameW(pszDirectoryPath, _countof(szFullPath), szFullPath, NULL); new CDirectoryWatcher(hNotifyWnd, pszDirectoryPath, fSubTree);
CDirectoryWatcher *pDirectoryWatcher = new CDirectoryWatcher(szFullPath, fSubTree);
if (pDirectoryWatcher->m_hDirectory == INVALID_HANDLE_VALUE) if (pDirectoryWatcher->m_hDirectory == INVALID_HANDLE_VALUE)
{ {
ERR("CreateFileW failed\n"); ERR("CreateFileW failed\n");
@ -103,7 +102,7 @@ CDirectoryWatcher::Create(LPCWSTR pszDirectoryPath, BOOL fSubTree)
CDirectoryWatcher::~CDirectoryWatcher() CDirectoryWatcher::~CDirectoryWatcher()
{ {
TRACE("CDirectoryWatcher::~CDirectoryWatcher: %p, '%S'\n", this, m_szDirectoryPath); TRACE("%p, '%S'\n", this, m_szDirectoryPath);
if (m_hDirectory != INVALID_HANDLE_VALUE) if (m_hDirectory != INVALID_HANDLE_VALUE)
CloseHandle(m_hDirectory); CloseHandle(m_hDirectory);
@ -385,10 +384,17 @@ void CDirectoryWatcher::QuitWatching()
assert(this != NULL); assert(this != NULL);
m_fDead = TRUE; m_fDead = TRUE;
m_hNotifyWnd = NULL;
CancelIo(m_hDirectory); CancelIo(m_hDirectory);
} }
BOOL CDirectoryWatcher::IsDead() const BOOL CDirectoryWatcher::IsDead()
{ {
if (m_hNotifyWnd && !::IsWindow(m_hNotifyWnd))
{
m_hNotifyWnd = NULL;
m_fDead = TRUE;
CancelIo(m_hDirectory);
}
return m_fDead; return m_fDead;
} }

View file

@ -17,11 +17,11 @@ public:
HANDLE m_hDirectory; HANDLE m_hDirectory;
WCHAR m_szDirectoryPath[MAX_PATH]; WCHAR m_szDirectoryPath[MAX_PATH];
static CDirectoryWatcher *Create(LPCWSTR pszDirectoryPath, BOOL fSubTree); static CDirectoryWatcher *Create(HWND hNotifyWnd, LPCWSTR pszDirectoryPath, BOOL fSubTree);
static void RequestAllWatchersTermination(); static void RequestAllWatchersTermination();
~CDirectoryWatcher(); ~CDirectoryWatcher();
BOOL IsDead() const; BOOL IsDead();
BOOL RestartWatching(); BOOL RestartWatching();
void QuitWatching(); void QuitWatching();
BOOL RequestAddWatcher(); BOOL RequestAddWatcher();
@ -29,6 +29,7 @@ public:
void ReadCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered); void ReadCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered);
protected: protected:
HWND m_hNotifyWnd;
BOOL m_fDead; BOOL m_fDead;
BOOL m_fRecursive; BOOL m_fRecursive;
CDirectoryList m_dir_list; CDirectoryList m_dir_list;
@ -36,5 +37,5 @@ protected:
BOOL CreateAPCThread(); BOOL CreateAPCThread();
void ProcessNotification(); void ProcessNotification();
CDirectoryWatcher(LPCWSTR pszDirectoryPath, BOOL fSubTree); CDirectoryWatcher(HWND hNotifyWnd, LPCWSTR pszDirectoryPath, BOOL fSubTree);
}; };