From 42ebf0eca543eb74c6069d705d0ed0924c5c6132 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand <seth@kipro-pcb.com> Date: Thu, 9 May 2024 15:28:38 -0700 Subject: [PATCH] Limit FSWatcher Library watches only need a single directory or immediate children. The project watcher should have a sensible limit to the total number of files it tries to track. Fixes https://gitlab.com/kicad/code/kicad/-/issues/15717 --- common/advanced_config.cpp | 7 +++++++ eeschema/sch_base_frame.cpp | 2 +- include/advanced_config.h | 10 ++++++++++ kicad/project_tree_pane.cpp | 7 ++++++- pcbnew/pcb_base_frame.cpp | 2 +- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp index 7bab16d597..78659f9822 100644 --- a/common/advanced_config.cpp +++ b/common/advanced_config.cpp @@ -111,6 +111,7 @@ static const wxChar TriangulateSimplificationLevel[] = wxT( "TriangulateSimplifi static const wxChar TriangulateMinimumArea[] = wxT( "TriangulateMinimumArea" ); static const wxChar EnableCacheFriendlyFracture[] = wxT( "EnableCacheFriendlyFracture" ); static const wxChar EnableAPILogging[] = wxT( "EnableAPILogging" ); +static const wxChar MaxFileSystemWatchers[] = wxT( "MaxFileSystemWatchers" ); } // namespace KEYS @@ -265,6 +266,8 @@ ADVANCED_CFG::ADVANCED_CFG() m_EnableCacheFriendlyFracture = true; + m_MaxFilesystemWatchers = 16384; + loadFromConfigFile(); } @@ -487,6 +490,10 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg ) &m_EnableCacheFriendlyFracture, m_EnableCacheFriendlyFracture ) ); + configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::MaxFileSystemWatchers, + &m_MaxFilesystemWatchers, m_MaxFilesystemWatchers, + 0, 2147483647 ) ); + // Special case for trace mask setting...we just grab them and set them immediately // Because we even use wxLogTrace inside of advanced config wxString traceMasks; diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp index e81aacc003..67aceaddd7 100644 --- a/eeschema/sch_base_frame.cpp +++ b/eeschema/sch_base_frame.cpp @@ -688,7 +688,7 @@ void SCH_BASE_FRAME::setSymWatcher( const LIB_ID* aID ) fn.AssignDir( m_watcherFileName.GetPath() ); fn.DontFollowLink(); - m_watcher->AddTree( fn ); + m_watcher->Add( fn ); } diff --git a/include/advanced_config.h b/include/advanced_config.h index bb7d05a4e4..978ca53527 100644 --- a/include/advanced_config.h +++ b/include/advanced_config.h @@ -580,6 +580,16 @@ public: * Log IPC API requests and responses */ bool m_EnableAPILogging; + + /** + * Maximum number of filesystem watchers to use. + * + * Setting name: "MaxFilesystemWatchers" + * Valid values: 0 to 2147483647 + * Default value: 16384 + */ + int m_MaxFilesystemWatchers; + ///@} private: diff --git a/kicad/project_tree_pane.cpp b/kicad/project_tree_pane.cpp index 6fc673cf39..6d28a0a6ff 100644 --- a/kicad/project_tree_pane.cpp +++ b/kicad/project_tree_pane.cpp @@ -1435,8 +1435,9 @@ void PROJECT_TREE_PANE::FileWatcherReset() std::stack < wxTreeItemId > subdirs_id; wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie ); + int total_watch_count = 0; - while( true ) + while( total_watch_count < ADVANCED_CFG::GetCfg().m_MaxFilesystemWatchers ) { if( !kid.IsOk() ) { @@ -1468,6 +1469,7 @@ void PROJECT_TREE_PANE::FileWatcherReset() { fn.AssignDir( path ); m_watcher->Add( fn ); + total_watch_count++; // if kid is a subdir, push in list to explore it later if( itemData->IsPopulated() && m_TreeProject->GetChildrenCount( kid ) ) @@ -1479,6 +1481,9 @@ void PROJECT_TREE_PANE::FileWatcherReset() } #endif + if( total_watch_count >= ADVANCED_CFG::GetCfg().m_MaxFilesystemWatchers ) + wxLogTrace( tracePathsAndFiles, "%s: too many directories to watch\n", __func__ ); + #if defined(DEBUG) && 1 wxArrayString paths; m_watcher->GetWatchedPaths( &paths ); diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp index d5fbfde55f..b6930dce96 100644 --- a/pcbnew/pcb_base_frame.cpp +++ b/pcbnew/pcb_base_frame.cpp @@ -1185,7 +1185,7 @@ void PCB_BASE_FRAME::setFPWatcher( FOOTPRINT* aFootprint ) wxLogTrace( "KICAD_LIB_WATCH", "Add watch: %s", fn.GetPath() ); - m_watcher->AddTree( fn ); + m_watcher->Add( fn ); }