mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-09-22 22:24:56 +08:00
Don't stop MSW wxFileSystemWatcher when a watched directory is deleted
The IOCP worker thread exited when one of the watched directories was deleted, silently stopping the events for all the other watches of the same wxFileSystemWatcher. Just stop reading the events for the deleted directory and keep processing the other ones.
This commit is contained in:
@@ -256,8 +256,9 @@ bool wxIOCPThread::ReadEvents()
|
||||
// It isn't useful to continue watching this directory as it
|
||||
// doesn't exist any more -- and even recreating a directory with
|
||||
// the same name still wouldn't resume generating events for the
|
||||
// existing wxIOCPService, so it's useless to continue.
|
||||
return false;
|
||||
// existing wxIOCPService, so don't start a new read for it. But
|
||||
// keep reading the events for all the other watches, if any.
|
||||
return true;
|
||||
|
||||
case wxIOCPService::Status_Exit:
|
||||
return false; // stop reading events
|
||||
|
||||
@@ -925,4 +925,92 @@ TEST_CASE_METHOD(FileSystemWatcherTestCase,
|
||||
tester.Run();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// TestEventsAfterDeletingWatchedDir
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Watches two directories, deletes one of them and checks that the events for the other one are
|
||||
// still received.
|
||||
class DeletedDirTester : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
DeletedDirTester() : m_timeout(this)
|
||||
{
|
||||
Bind(wxEVT_FSWATCHER, &DeletedDirTester::OnFileSystemEvent, this);
|
||||
Bind(wxEVT_TIMER, &DeletedDirTester::OnTimeout, this);
|
||||
|
||||
// wxFileSystemWatcher can be created only once the event loop is running.
|
||||
CallAfter(&DeletedDirTester::DoTest);
|
||||
}
|
||||
|
||||
void Run() { m_loop.Run(); }
|
||||
|
||||
bool GotEventForKeptDir() const { return m_gotEvent; }
|
||||
|
||||
private:
|
||||
void DoTest()
|
||||
{
|
||||
const wxFileName& base = EventGenerator::Get().GetWatchDir();
|
||||
|
||||
wxFileName deletedDir;
|
||||
deletedDir.AssignDir(base.GetFullPath());
|
||||
deletedDir.AppendDir("deleted");
|
||||
REQUIRE( deletedDir.Mkdir() );
|
||||
|
||||
wxFileName keptDir;
|
||||
keptDir.AssignDir(base.GetFullPath());
|
||||
keptDir.AppendDir("kept");
|
||||
REQUIRE( keptDir.Mkdir() );
|
||||
|
||||
m_watcher.reset(new wxFileSystemWatcher());
|
||||
m_watcher->SetOwner(this);
|
||||
REQUIRE( m_watcher->Add(deletedDir) );
|
||||
REQUIRE( m_watcher->Add(keptDir) );
|
||||
|
||||
REQUIRE( deletedDir.Rmdir() );
|
||||
wxMilliSleep(200);
|
||||
|
||||
m_file = wxFileName(keptDir.GetFullPath(), "test.txt");
|
||||
wxFile file(m_file.GetFullPath(), wxFile::write);
|
||||
REQUIRE( file.IsOpened() );
|
||||
|
||||
// Don't wait forever if the event is never received.
|
||||
m_timeout.Start(3000, wxTIMER_ONE_SHOT);
|
||||
}
|
||||
|
||||
void OnFileSystemEvent(wxFileSystemWatcherEvent& evt)
|
||||
{
|
||||
if ( evt.GetPath() == m_file )
|
||||
{
|
||||
m_gotEvent = true;
|
||||
m_loop.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
void OnTimeout(wxTimerEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_loop.Exit();
|
||||
}
|
||||
|
||||
wxEventLoop m_loop;
|
||||
wxTimer m_timeout;
|
||||
std::unique_ptr<wxFileSystemWatcher> m_watcher;
|
||||
wxFileName m_file;
|
||||
bool m_gotEvent = false;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
TEST_CASE_METHOD(FileSystemWatcherTestCase,
|
||||
"wxFileSystemWatcher::EventsAfterDeletingWatchedDir", "[fsw]")
|
||||
{
|
||||
DeletedDirTester tester;
|
||||
tester.Run();
|
||||
|
||||
CHECK( tester.GotEventForKeptDir() );
|
||||
}
|
||||
|
||||
#endif // wxUSE_FSWATCHER
|
||||
|
||||
Reference in New Issue
Block a user