@@ -37,7 +37,9 @@ internal class AssemblyManager
3737
3838 // modified from event handlers below, potentially triggered from different .NET threads
3939 private static readonly ConcurrentQueue < Assembly > assemblies = new ( ) ;
40- internal static readonly List < string > pypath = new ( capacity : 16 ) ;
40+ // Snapshot; UpdatePath swaps under lock, readers iterate the captured ref.
41+ internal static volatile IReadOnlyList < string > pypath = Array . Empty < string > ( ) ;
42+ private static readonly object _pypathLock = new ( ) ;
4143 private AssemblyManager ( )
4244 {
4345 }
@@ -49,7 +51,7 @@ private AssemblyManager()
4951 //github.com/ </summary>
5052 internal static void Initialize ( )
5153 {
52- pypath . Clear ( ) ;
54+ pypath = Array . Empty < string > ( ) ;
5355
5456 AppDomain domain = AppDomain . CurrentDomain ;
5557
@@ -154,19 +156,20 @@ internal static void UpdatePath()
154156 {
155157 BorrowedReference list = Runtime . PySys_GetObject ( "path" ) ;
156158 var count = Runtime . PyList_Size ( list ) ;
157- if ( count != pypath . Count )
159+ if ( count == pypath . Count ) return ;
160+
161+ lock ( _pypathLock )
158162 {
159- pypath . Clear ( ) ;
163+ if ( count == pypath . Count ) return ;
164+ var fresh = new List < string > ( checked ( ( int ) count ) ) ;
160165 probed . Clear ( ) ;
161166 for ( var i = 0 ; i < count ; i ++ )
162167 {
163168 BorrowedReference item = Runtime . PyList_GetItem ( list , i ) ;
164169 string ? path = Runtime . GetManagedString ( item ) ;
165- if ( path != null )
166- {
167- pypath . Add ( path ) ;
168- }
170+ if ( path != null ) fresh . Add ( path ) ;
169171 }
172+ pypath = fresh ;
170173 }
171174 }
172175
@@ -196,7 +199,8 @@ public static string FindAssembly(string name)
196199
197200 static IEnumerable < string > FindAssemblyCandidates ( string name )
198201 {
199- foreach ( string head in pypath )
202+ var paths = pypath ;
203+ foreach ( string head in paths )
200204 {
201205 string path ;
202206 if ( head == null || head . Length == 0 )
0 commit comments