[Insight-developers] Static initialization in itkImageSource causes early registration of ITKIOFactory
Bradley Lowekamp
blowekamp at mail.nih.gov
Thu Apr 4 08:48:49 EDT 2013
JC,
On Apr 3, 2013, at 2:13 PM, Jean-Christophe Fillion-Robin <jchris.fillionr at kitware.com> wrote:
> 1) A possible way of checking this would be to check if an env variable named ITK_OBJECT_FACTORY_BASE_INITIALIZE_VERBOSE is defined to 1, if it is the case, the number of registered factory would be displayed in the "ObjectFactoryBase::Initialize()" methods.
Interesting idea... I think making use out of a REGEX of the output is a good idea. I think we could add some itkDebugMacro output to the method to achieve this. To actually get the output we would need to compile in debug mode and turn on the Debug IVAR for the class... It think is should work though.
Would this be of any help for tracking down these related issues in Slicer? I think you ENV option was designed to help you track this issue down :)
>
> Then writing a hello world program linking against ITK, would allow to check if the "hello world" string is displayed before or after static initialization.
>
> 2) I think the addition of a ITKFactoryRegistration shared library would be backward compatible. Application would be either using their inside hack or calling the method provided by ITK allowing to register the factories. Let's also note that all of this would be needed only if the variable ITK_NO_IO_FACTORY_REGISTER_MANAGER is set to True.
I would strongly advocate that if we start to add something like this we just make it general. Is should just be "Initialization", while currently it'd just be the factory registration, it keeps things open for other operations that may need to be done in the future.
In addition to the compatibility issues, I also forgot about the modularization issues. Such a library would be linked against all ITK libraries.
>
> I really think this would benefit every application loading plugin.
>
> 3) A different approach would be to check if a given factory is already loaded and ensure that no duplicate factory are registered.
From the C++ perspective they are not duplicate factories they are different object :)
Because on windows each of the factories libraries are static libraries, each plugin is linked and includes symbols for those objects. So each module has a different object factory in the C++ sense. If you try to do a dynamic_casts on these object created in one plugin or library, and used in another they will fail because in the C++ linking sense they are different objects, with different vtables.
This is only an issue on a windows project with a large number of plugins.
Why not pursue making all ITK object factories come from shared libraries? That would also fix this problem.
4) Make the FactoryHasBeenRegistered flag, exist in the Common library.
Another option which just occurred to me is the problem could also be seen as the following variable occurs multiple time due to the static libraries in windows:
https://github.com/Kitware/ITK/blob/master/Modules/IO/NRRD/src/itkNrrdImageIOFactory.cxx#L51
If we could some how get that flag to exist in the ITKCommon library inside some data structure. I think this may be a little tricky but should be do able with some function called during static initialization and function scoped static variables.
What I don't understand, that I hope Brad K. could explain, is why this static "HasBeenRegistered" variable was used instead of a mechanism which gives each factory a unique ID, and ensuring it only get's registered in the factory one.
Brad
>
> Let me know what you think.
>
> Thanks
> Jc
>
>
> On Wed, Apr 3, 2013 at 1:25 PM, Bradley Lowekamp <blowekamp at mail.nih.gov> wrote:
> Bill,
>
> There is currently no an obvious way I see to check this. If you call a method of the ObjectFactory to ask how many object are registered, it will do the initialization if it wasn't before.
>
> Now a new method could be added, to check if the ObjectFactory has been initialized. But I recall there was quite a lot of issues with the class on when the initialization should occur and how to check if it needs to be done.
>
> Brad
>
> On Apr 3, 2013, at 12:35 PM, Bill Lorensen <bill.lorensen at gmail.com> wrote:
>
>> Brad,
>>
>> Is there a way we can test for this in ITK? Better we find it before our customers.
>>
>> Bill
>>
>>
>> On Wed, Apr 3, 2013 at 12:11 PM, Jean-Christophe Fillion-Robin <jchris.fillionr at kitware.com> wrote:
>> Thanks Brad for looking at the issue so quickly :)
>>
>> I reviewed your patch in gerrit and posted comment.
>>
>> Thanks
>> Jc
>>
>>
>> On Wed, Apr 3, 2013 at 11:33 AM, Bradley Lowekamp <blowekamp at mail.nih.gov> wrote:
>> Hello JC,
>>
>> This is quite an interesting side-effect of the changes I introduced.
>>
>> I am glad that you were able to figure this out. For a variety of reasons, it's likely a very bad thing for all that to occur during static initialization in ITK. So it certainly needs to be fixed.
>>
>> I agree that lazy initialization is the way to go. Unfortunately it needs to be thread safe so its a little more completed.
>>
>> ITKv4 performs the factory initialization when the user creates the first ITK object. And that changed with this patch, and need to be fixed.
>>
>> CONCLUSION:
>>
>> Inside ITK, we can not use statically initialized ITK object.
>>
>> Brad
>>
>> On Apr 3, 2013, at 10:54 AM, Jean-Christophe Fillion-Robin <jchris.fillionr at kitware.com> wrote:
>>
>>> Hi Brad,
>>>
>>> Following commit 4c47e7d [1] of February 19th and commit defb9c1 [2] of March 1st, due to static initialization, the initialization of ObjectFactory now happens when ITK shared library are loaded [3][4].
>>>
>>> This caused a regression in Slicer where the ObjectFactory were expected to be loaded while attempting to load an image for the first time.
>>>
>>> In Slicer case, the environment variable ITK_AUTOLOAD_PATH was set during the initialization of the qSlicerCoreApplication, which is now too late.
>>>
>>> By commenting line where a new ImageRegionSplitterSlowDimension is instantiated [5][6] and updating the method "GetImageRegionSplitter / GetGlobalDefaultSplitter" to return 0 [7][8], the initialization can happen on demand instead of when ITK libraries are loaded.
>>>
>>> An easy solution for us would be to ensure the "ITK_AUTOLOAD_PATH" environment variable is set in the application launcher for Windows and Linux application and set in Info.plist file associated with the application bundle on MacOSX [9]
>>>
>>> To provide more details, within Slicer we set the CMake variable ITK_NO_IO_FACTORY_REGISTER_MANAGER before doing an "include(${ITK_USE_FILE}) so that IOFactory are loaded only by calling the method "itkFactoryRegistration" associated with a shared library we named ITKFactoryRegistration. This approach allowed us to disable the automatic registration of factory in selected part of the code. More details here [10]
>>>
>>> It seems the new ITK commits 4c47e7d and defb9c1 prevent from completely leveraging the use of ITK_NO_IO_FACTORY_REGISTER_MANAGER variable, the code should probably be updated to consider this.
>>>
>>>
>>> Let me know what you think.
>>>
>>> Thanks
>>> Jc
>>>
>>>
>>> [1] https://github.com/Kitware/ITK/commit/4c47e7d
>>> [2] https://github.com/Kitware/ITK/commit/defb9c1
>>> [3] https://github.com/Kitware/ITK/blob/4c47e7d672bad5d83b92c2df5f293cca618e2740/Modules/Core/Common/src/itkImageSource.cxx#L27
>>> [4] https://github.com/Kitware/ITK/blob/4c47e7d672bad5d83b92c2df5f293cca618e2740/Modules/Core/Common/src/itkObjectFactoryBase.cxx#L142-144
>>> [5] https://github.com/Kitware/ITK/blob/defb9c1d084c8d55df61947587427839f9968ecf/Modules/IO/ImageBase/src/itkImageIOBase.cxx#L760
>>> [6] https://github.com/Kitware/ITK/blob/4c47e7d672bad5d83b92c2df5f293cca618e2740/Modules/Core/Common/src/itkImageSource.cxx#L27
>>> [7] https://github.com/Kitware/ITK/blob/defb9c1d084c8d55df61947587427839f9968ecf/Modules/IO/ImageBase/src/itkImageIOBase.cxx#L765
>>> [8] https://github.com/Kitware/ITK/blob/4c47e7d672bad5d83b92c2df5f293cca618e2740/Modules/Core/Common/src/itkImageSource.cxx#L32
>>> [9] http://www.herzbube.ch/blog/2009/01/how-set-environment-variables-mac-os-x-applications
>>> [10] https://github.com/Slicer/Slicer/commit/03b8961
>>>
>>> --
>>> +1 919 869 8849
>>> _______________________________________________
>>> Powered by www.kitware.com
>>>
>>> Visit other Kitware open-source projects at
>>> http://www.kitware.com/opensource/opensource.html
>>>
>>> Kitware offers ITK Training Courses, for more information visit:
>>> http://kitware.com/products/protraining.php
>>>
>>> Please keep messages on-topic and check the ITK FAQ at:
>>> http://www.itk.org/Wiki/ITK_FAQ
>>>
>>> Follow this link to subscribe/unsubscribe:
>>> http://www.itk.org/mailman/listinfo/insight-developers
>>
>>
>>
>>
>> --
>> +1 919 869 8849
>>
>> _______________________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at
>> http://www.kitware.com/opensource/opensource.html
>>
>> Kitware offers ITK Training Courses, for more information visit:
>> http://kitware.com/products/protraining.php
>>
>> Please keep messages on-topic and check the ITK FAQ at:
>> http://www.itk.org/Wiki/ITK_FAQ
>>
>> Follow this link to subscribe/unsubscribe:
>> http://www.itk.org/mailman/listinfo/insight-developers
>>
>>
>>
>>
>> --
>> Unpaid intern in BillsBasement at noware dot com
>
>
>
>
> --
> +1 919 869 8849
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.itk.org/pipermail/insight-developers/attachments/20130404/fb406a29/attachment.htm>
More information about the Insight-developers
mailing list