# GetConstructorInfo exception on multiple thread

**URL:** https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753
**Category:** Support
**Created:** [November 20, 2023, 3:04am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753 "2023-11-20T03:04:58Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![liuzhongshu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/liuzhongshu/32/6921_2.png) [@liuzhongshu](https://discourse.vtk.org/u/liuzhongshu)
#### Post date: [November 20, 2023, 3:04am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/1 "2023-11-20T03:04:58Z")

</div>

I am using [Activz.Net](http://Activz.Net) 9, and want to async load multiple obj files, so I use multiple thread, but I will get GetConstructorInfo exception as following:

```auto
System.Exception: error: IndexedConstructors table already has a non-null entry at mteIndex 43
   在 Kitware.mummy.Runtime.Methods.GetConstructorInfo(UInt32 mteIndex)
   在 Kitware.mummy.Runtime.Methods.CreateWrappedObjectImpl(UInt32 mteStatus, UInt32 mteIndex, UInt32 rawRefCount, IntPtr rawCppThis, Boolean callDisposalMethod, Boolean& created)
   在 Kitware.mummy.Runtime.Methods.CreateWrappedObject(UInt32 mteStatus, UInt32 mteIndex, UInt32 rawRefCount, IntPtr rawCppThis, Boolean callDisposalMethod, Boolean& found)

```

After some research, I found that the following simple code can reproduce the problem:

```auto
for (int i = 0; i < 3; i++)
{
    Task.Run(() => { vtkUnsignedCharArray.New(); });
 }

```

So, is there a problem with my usage? Are there any restrictions in vtk? I don’t need the multi-threading of the pipeline, I just load multiple obj files asynchronously.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)
#### Post date: [November 20, 2023, 12:52pm UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/2 "2023-11-20T12:52:41Z")

</div>

Cc: @mwestphal

---

<div class="post-metadata">

### Author: ![mwestphal](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mwestphal/32/19_2.png) [@mwestphal](https://discourse.vtk.org/u/mwestphal)
#### Post date: [November 20, 2023, 1:10pm UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/3 "2023-11-20T13:10:12Z")

</div>

@LucasGandel

---

<div class="post-metadata">

### Author: ![LucasGandel](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lucasgandel/32/1831_2.png) [@LucasGandel](https://discourse.vtk.org/u/LucasGandel)
#### Post date: [November 23, 2023, 11:06am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/4 "2023-11-23T11:06:07Z")

</div>

The exception results from a concurrent access to the mummy internal table that stores the C# references to VTK objects.  
Activiz is not thread safe, you can’t create objects with such an approach. However you can probably use a native C# array to load your data and then copy it to your vtkUnsignedCharArray in the main thread using marshalling.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [November 23, 2023, 11:20am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/5 "2023-11-23T11:20:21Z")

</div>

> Activiz is not thread safe, you can’t create objects with such an approach.

It used to be thread safe. It synchronised on the wrapped objects table. Has this changed?

```auto
   /// <summary>
   /// Factory method to create a wrapped object from a registered TypeEntry.
   /// Client dlls that provide objects should register their known types via
   /// RegisterType prior to any possible call to CreateWrappedObject.
   /// </summary>
   private object CreateWrappedObjectImpl(uint mteStatus, uint mteIndex, uint rawRefCount, System.IntPtr rawCppThis, bool callDisposalMethod, out bool created)
   {
      object obj = null;

      if (null != this.WrappedObjectsTable)
      {
        lock(this.WrappedObjectsTable.SyncRoot)
        {
           obj = this.WrappedObjectsTable[rawCppThis];

           System.WeakReference wr = obj as System.WeakReference;
           if (null != wr)
           {
              obj = wr.Target;
           }
        }
      }

      if (null != obj)
      {
         created = false;
         ++WrappedObjectsTableHits;
      }
      else
      {
         created = true;
         ++WrappedObjectsTableMisses;

         // Get a constructor info for the type of the object we're supposed
         // to create via mteIndex:
         //
         System.Reflection.ConstructorInfo ci = GetConstructorInfo(mteIndex);

         // Invoke the constructor with parameters:
         bool strong = true;
         if (0 == mteStatus || rawRefCount < 2)
         {
            strong = false;
         }

         object[] ctorParams = new object[3];
         ctorParams[0] = rawCppThis;
         ctorParams[1] = callDisposalMethod;
         ctorParams[2] = strong;

         obj = ci.Invoke(ctorParams);
      }

      return obj;
   }

```

---

<div class="post-metadata">

### Author: ![LucasGandel](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lucasgandel/32/1831_2.png) [@LucasGandel](https://discourse.vtk.org/u/LucasGandel)
#### Post date: [November 23, 2023, 12:20pm UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/6 "2023-11-23T12:20:30Z")

</div>

The code has not changed. The WrappedObjectsTable is locked but the IndexedConstructors is not. Adding `lock (Instance.IndexedConstructors.SyncRoot)` in `GetConstructorInfo` will probably fix the problem here, but I am not sure this is enough to make Activiz thread safe in general. Classes that use vtkGarbageCollector internally are not well handled by the C# GC.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [November 23, 2023, 9:32pm UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/7 "2023-11-23T21:32:08Z")

</div>

I think the problem is that

```auto
lock(this.WrappedObjectsTable.SyncRoot)

```

is going out of scope before the constructor is called. Moving the constructor invocation inside the `if` block might fix that. You have a simple use case to test against.

---

<div class="post-metadata">

### Author: ![liuzhongshu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/liuzhongshu/32/6921_2.png) [@liuzhongshu](https://discourse.vtk.org/u/liuzhongshu)
#### Post date: [November 24, 2023, 4:04am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/8 "2023-11-24T04:04:36Z")

</div>

> [@LucasGandel](#):
>
> Activiz is not thread safe, you can’t create objects with such an approach.

If the Visualization pipeline is not thread safe, I think it might be ok. But if independent data objects are not thread-safe, the code will be difficult to write.

---

<div class="post-metadata">

### Author: ![LucasGandel](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lucasgandel/32/1831_2.png) [@LucasGandel](https://discourse.vtk.org/u/LucasGandel)
#### Post date: [November 24, 2023, 7:18am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/9 "2023-11-24T07:18:28Z")

</div>

While I agree that what you propose should work, I am not sure to understand why you don’t think that locking `IndexedConstructors` is the best approach? To me, it is the object affected by the race condition, WrappedObjectsTable is not used at this point.  
Anyway, I agree we have a simple test case to reproduce and it is worth having a look.

---

<div class="post-metadata">

### Author: ![liuzhongshu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/liuzhongshu/32/6921_2.png) [@liuzhongshu](https://discourse.vtk.org/u/liuzhongshu)
#### Post date: [November 24, 2023, 7:22am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/10 "2023-11-24T07:22:01Z")

</div>

I’m not worried about this specific problem, I’m worried about whether there will be similar problems in other places, so that my vtk related code must be completely single-threaded.

---

<div class="post-metadata">

### Author: ![LucasGandel](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lucasgandel/32/1831_2.png) [@LucasGandel](https://discourse.vtk.org/u/LucasGandel)
#### Post date: [November 24, 2023, 7:35am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/11 "2023-11-24T07:35:40Z")

</div>

Yes we advise that your VTK code must be single threaded in general, as there will be similar problems in other places. It does not mean that we can’t give it a try, and this specific problem must be fixed for that. Having completely independent filters that don’t share inputs, and that don’t use pipelines could potentially work. This should be investigated further to clearly identify what is supported and what is not.  
Maybe @alexy.pellegrini has inputs?

---

<div class="post-metadata">

### Author: ![liuzhongshu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/liuzhongshu/32/6921_2.png) [@liuzhongshu](https://discourse.vtk.org/u/liuzhongshu)
#### Post date: [November 24, 2023, 7:46am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/12 "2023-11-24T07:46:15Z")

</div>

Thanks for the clarification, I understand. I have tested some asynchronous scenarios, mainly asynchronously loading some mesh and color data using vtkPolyData for VTK. So far, except for this problem, other asynchronous scenarios are working very well.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [November 25, 2023, 2:05am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/13 "2023-11-25T02:05:13Z")

</div>

> While I agree that what you propose should work, I am not sure to understand why you don’t think that locking `IndexedConstructors` is the best approach?

Because the c# constructor adds the new object to the `WrappedObjectsTable` hash table. If another thread tries to create an object with the same underlying c++ instance, e.g. during deserialisation, a race condition will ensue. Holding the lock until after construction prevents the clash.

So that’s one problem eliminated.

However in the use case suggested by @liuzhongshu the error seems to be related to the way the `IndexedConstructors` array is being populated at runtime as wrapped objects are created. So locking on `IndexedConstructors` would fix that issue but a better solution would be to setup `IndexedConstructors` during application initialisation.

Synchronising on `WrappedObjectsTable` resolves both issues.

> [@LucasGandel](#):
>
> Having completely independent filters that don’t share inputs, and that don’t use pipelines could potentially work.

If VTK itself supports multi-threading with pipelines and shared inputs then I would expect the c# wrapper code should too.

---

<div class="post-metadata">

### Author: ![alexy.pellegrini](https://discourse.vtk.org/user_avatar/discourse.vtk.org/alexy.pellegrini/32/5887_2.png) [@alexy.pellegrini](https://discourse.vtk.org/u/alexy.pellegrini)
#### Post date: [November 28, 2023, 8:43am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/14 "2023-11-28T08:43:53Z")

</div>

Hi everyone,

There are two things to take into account!

VTK pipelines aren’t thread safe regardless of their inputs and outputs. This is due the VTK garbage collector pipeline related object (`vtkAlgorithm`, `vtkInformation` and `vtkExecutive`) because they hold strong cyclic references to each others.  
VTK GC can only run in the main thread, and is called on every `Delete()` or those types, and some will fire internally on the `Update()` of the algorithm, due to information vectors being created and destroyed at some point.  
As long as this GC is used, it will be UB to update, delete, and maybe even constructing, algorithms in multiple thread, or even in a thread that isn’t the main thread. Note: if you build in debug (without NDEBUG defined actually), you may trigger [an assertion in VTK GC](https://gitlab.kitware.com/vtk/vtk/-/blob/master/Common/Core/vtkGarbageCollector.cxx?ref_type=heads#L864).  
[There is an issue](https://gitlab.kitware.com/vtk/vtk/-/issues/18484), opened a year ago by @jaswantp that is related to this exact problem.

In short: you can’t safely use VTK algorithm in multiple threads, regardless of their inputs and outputs. And this is a VTK issue. Other VTK classes does not have this limitation, and are safe to be create and destroyed in any thread AFAIK.

Activiz classes creation and registration should indeed be thread safe, and I agree that it should be considered a bug that it isn’t supported correctly.

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [December 28, 2023, 3:37pm UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/15 "2023-12-28T15:37:41Z")

</div>

> [There is an issue](https://gitlab.kitware.com/vtk/vtk/-/issues/18484), opened a year ago by @jaswantp that is related to this exact problem.

> In short: you can’t safely use VTK algorithm in multiple threads, regardless of their inputs and outputs. And this is a VTK issue. Other VTK classes does not have this limitation, and are safe to be create and destroyed in any thread AFAIK.

FYI, we’ve found a way to get around this limitation in MR [vtk/vtk!8975](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/8975). @berk.geveci iirc, we started working on it for async-paraview, then moved on to other priorities. Is there anything else needed on that to land?

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [December 28, 2023, 4:20pm UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/16 "2023-12-28T16:20:31Z")

</div>

@jaswantp Let’s please get that change merged.

@alexy.pellegrini Your description is slightly confusing so I want to clarify a little bit. You can use VTK pipelines in a multi-threaded way as long as all threads have completely different algorithms. The thread safety issue arises only when algorithms are shared across threads (and things are deleted) leading to potential garbage collection thread issues. Even after @jaswantp 's change, I would not recommend using the same algorithm in multiple threads (except maybe with locks and only to manage the state from one thread).  
What @alexy.pellegrini and I are talking about is a thread safety issue at the C++ level. The C# issues discussed in this thread seem to be on top of the C++ issues.

---

<div class="post-metadata">

### Author: ![LucasGandel](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lucasgandel/32/1831_2.png) [@LucasGandel](https://discourse.vtk.org/u/LucasGandel)
#### Post date: [January 3, 2024, 10:03am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/17 "2024-01-03T10:03:00Z")

</div>

Thank you so much for your insight @berk.geveci ! This is great news that things are moving forward in VTK.  
  
I confirm the C# issue reported in this thread is on top of the C++ issues you mention, and it will be fixed in the next Activiz release.  
  
Then, the VTK C++ issues have further impact in C#, where the GC is generally running in a background thread. Here disabling the VTK GC is the only way to prevent an undefined behavior where the C# GC deletes a pipeline while the VTK GC is checking for references. We will give a quick try to @jaswantp’s change to see if things are improved there.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [January 4, 2024, 1:17am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/18 "2024-01-04T01:17:43Z")

</div>

@LucasGandel So which solution did you choose? Locking on WrappedObjectsTable or locking on IndexedConstructors?

---

<div class="post-metadata">

### Author: ![LucasGandel](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lucasgandel/32/1831_2.png) [@LucasGandel](https://discourse.vtk.org/u/LucasGandel)
#### Post date: [January 4, 2024, 7:33am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/19 "2024-01-04T07:33:13Z")

</div>

Both, and even other collections.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [January 4, 2024, 8:44am UTC](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753/20 "2024-01-04T08:44:17Z")

</div>

Why both? You don’t need both. It just adds a performance penalty.

[Next page](https://discourse.vtk.org/t/getconstructorinfo-exception-on-multiple-thread/12753.md?page=2)
