| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,6 +29,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. | |||
| 29 | 29 | - Fixed 'clrmethod' for python 2 (#492) | |
| 30 | 30 | - Fixed double calling of constructor when deriving from .NET class (#495) | |
| 31 | 31 | - Fixed `clr.GetClrType` when iterating over `System` members (#607) | |
| 32 | + - Fixed `LockRecursionException` when loading assemblies (#627) | ||
| 32 | 33 | ||
| 33 | 34 | ||
| 34 | 35 | ## [2.3.0][] - 2017-03-11 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,7 +26,7 @@ internal class AssemblyManager | |||
| 26 | 26 | private static Dictionary<string, int> probed; | |
| 27 | 27 | ||
| 28 | 28 | // modified from event handlers below, potentially triggered from different .NET threads | |
| 29 | - private static AssemblyList assemblies; | ||
| 29 | + private static ConcurrentQueue<Assembly> assemblies; | ||
| 30 | 30 | internal static List<string> pypath; | |
| 31 | 31 | ||
| 32 | 32 | private AssemblyManager() | |
@@ -43,7 +43,7 @@ internal static void Initialize() | |||
| 43 | 43 | namespaces = new ConcurrentDictionary<string, ConcurrentDictionary<Assembly, string>>(); | |
| 44 | 44 | probed = new Dictionary<string, int>(32); | |
| 45 | 45 | //generics = new Dictionary<string, Dictionary<string, string>>(); | |
| 46 | - assemblies = new AssemblyList(16); | ||
| 46 | + assemblies = new ConcurrentQueue<Assembly>(); | ||
| 47 | 47 | pypath = new List<string>(16); | |
| 48 | 48 | ||
| 49 | 49 | AppDomain domain = AppDomain.CurrentDomain; | |
@@ -60,7 +60,7 @@ internal static void Initialize() | |||
| 60 | 60 | try | |
| 61 | 61 | { | |
| 62 | 62 | ScanAssembly(a); | |
| 63 | - assemblies.Add(a); | ||
| 63 | + assemblies.Enqueue(a); | ||
| 64 | 64 | } | |
| 65 | 65 | catch (Exception ex) | |
| 66 | 66 | { | |
@@ -91,7 +91,7 @@ internal static void Shutdown() | |||
| 91 | 91 | private static void AssemblyLoadHandler(object ob, AssemblyLoadEventArgs args) | |
| 92 | 92 | { | |
| 93 | 93 | Assembly assembly = args.LoadedAssembly; | |
| 94 | - assemblies.Add(assembly); | ||
| 94 | + assemblies.Enqueue(assembly); | ||
| 95 | 95 | ScanAssembly(assembly); | |
| 96 | 96 | } | |
| 97 | 97 | ||
@@ -461,103 +461,5 @@ public static Type LookupType(string qname) | |||
| 461 | 461 | } | |
| 462 | 462 | return null; | |
| 463 | 463 | } | |
| 464 | - | ||
| 465 | - /// <summary> | ||
| 466 | - /// Wrapper around List<Assembly> for thread safe access | ||
| 467 | - /// </summary> | ||
| 468 | - private class AssemblyList : IEnumerable<Assembly> | ||
| 469 | - { | ||
| 470 | - private readonly List<Assembly> _list; | ||
| 471 | - private readonly ReaderWriterLockSlim _lock; | ||
| 472 | - | ||
| 473 | - public AssemblyList(int capacity) | ||
| 474 | - { | ||
| 475 | - _list = new List<Assembly>(capacity); | ||
| 476 | - _lock = new ReaderWriterLockSlim(); | ||
| 477 | - } | ||
| 478 | - | ||
| 479 | - public int Count | ||
| 480 | - { | ||
| 481 | - get | ||
| 482 | - { | ||
| 483 | - _lock.EnterReadLock(); | ||
| 484 | - try | ||
| 485 | - { | ||
| 486 | - return _list.Count; | ||
| 487 | - } | ||
| 488 | - finally | ||
| 489 | - { | ||
| 490 | - _lock.ExitReadLock(); | ||
| 491 | - } | ||
| 492 | - } | ||
| 493 | - } | ||
| 494 | - | ||
| 495 | - public void Add(Assembly assembly) | ||
| 496 | - { | ||
| 497 | - _lock.EnterWriteLock(); | ||
| 498 | - try | ||
| 499 | - { | ||
| 500 | - _list.Add(assembly); | ||
| 501 | - } | ||
| 502 | - finally | ||
| 503 | - { | ||
| 504 | - _lock.ExitWriteLock(); | ||
| 505 | - } | ||
| 506 | - } | ||
| 507 | - | ||
| 508 | - public IEnumerator GetEnumerator() | ||
| 509 | - { | ||
| 510 | - return ((IEnumerable<Assembly>)this).GetEnumerator(); | ||
| 511 | - } | ||
| 512 | - | ||
| 513 | - /// <summary> | ||
| 514 | - /// Enumerator wrapping around <see cref="AssemblyList._list" />'s enumerator. | ||
| 515 | - /// Acquires and releases a read lock on <see cref="AssemblyList._lock" /> during enumeration | ||
| 516 | - /// </summary> | ||
| 517 | - private class Enumerator : IEnumerator<Assembly> | ||
| 518 | - { | ||
| 519 | - private readonly AssemblyList _assemblyList; | ||
| 520 | - | ||
| 521 | - private readonly IEnumerator<Assembly> _listEnumerator; | ||
| 522 | - | ||
| 523 | - public Enumerator(AssemblyList assemblyList) | ||
| 524 | - { | ||
| 525 | - _assemblyList = assemblyList; | ||
| 526 | - _assemblyList._lock.EnterReadLock(); | ||
| 527 | - _listEnumerator = _assemblyList._list.GetEnumerator(); | ||
| 528 | - } | ||
| 529 | - | ||
| 530 | - public void Dispose() | ||
| 531 | - { | ||
| 532 | - _listEnumerator.Dispose(); | ||
| 533 | - _assemblyList._lock.ExitReadLock(); | ||
| 534 | - } | ||
| 535 | - | ||
| 536 | - public bool MoveNext() | ||
| 537 | - { | ||
| 538 | - return _listEnumerator.MoveNext(); | ||
| 539 | - } | ||
| 540 | - | ||
| 541 | - public void Reset() | ||
| 542 | - { | ||
| 543 | - _listEnumerator.Reset(); | ||
| 544 | - } | ||
| 545 | - | ||
| 546 | - public Assembly Current | ||
| 547 | - { | ||
| 548 | - get { return _listEnumerator.Current; } | ||
| 549 | - } | ||
| 550 | - | ||
| 551 | - object IEnumerator.Current | ||
| 552 | - { | ||
| 553 | - get { return Current; } | ||
| 554 | - } | ||
| 555 | - } | ||
| 556 | - | ||
| 557 | - IEnumerator<Assembly> IEnumerable<Assembly>.GetEnumerator() | ||
| 558 | - { | ||
| 559 | - return new Enumerator(this); | ||
| 560 | - } | ||
| 561 | - } | ||
| 562 | 464 | } | |
| 563 | 465 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -387,3 +387,9 @@ def test_assembly_load_thread_safety(): | |||
| 387 | 387 | from System.Collections.Generic import Dictionary | |
| 388 | 388 | _ = Dictionary[Guid, DateTime]() | |
| 389 | 389 | ModuleTest.JoinThreads() | |
| 390 | + | ||
| 391 | + def test_assembly_load_recursion_bug(): | ||
| 392 | + """Test fix for recursion bug documented in #627""" | ||
| 393 | + from System.Configuration import ConfigurationManager | ||
| 394 | + content = dir(ConfigurationManager) | ||
| 395 | + assert len(content) > 5, content | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments