celix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] [celix] pnoltes edited a comment on pull request #306: revive the export_import example
Date Sun, 06 Dec 2020 14:22:21 GMT

pnoltes edited a comment on pull request #306:
URL: https://github.com/apache/celix/pull/306#issuecomment-739509543


   Hi PengZheng, 
   
   Nice to see you working on the export / import example.
   The whole import/export library functionality for Celix has been dormant for quite some
time.
   
   The idea was of course that this should mimic the  Export-Package / Import-Package of OSGi
Module Layer. 
   Only in C there are no runtime packages, so the most logical thing to mimic the java packages
was shared libraries. 
   
   So bundles (zip files) with shared libraries (so/dylib files) and using dynamic library
loading (dlopen) should make this possible?.
   Well... the details are important.
   For example. Say you have a library `foo` and you have two bundles (`A` and `B`) exporting
a version of this library (1.8.0 and 2.0.0). You also have two bundles (`C` and `D`) importing
these libraries. C wants version [1,2) (so version 1 and up, but not 2 or higher than 2) and
D wants version [2,3).
   So 
   ```
   Bundle A  -- Export --> libfoo.so 1.8.0
   Bundle B  -- Export --> libfoo.so 2.0.0
   Bundle C <- Import --- libfoo.so [1,2)
   Bundle D <- Import --- libfoo.so [2,3)
   ```
   
   For this to really work we need to arrange quite some things. And to keep it simple I just
focusing on Linux. 
   ## SONAME
   The SONAME (field of data in a shared object file) for libfoo.so 1.0.0 and libfoo.so 2.0.0
need to be different. Even when using dlopen with RTLD_LOCAL, dlopen will just reuse symbols
already loaded if you load an already loaded library with the same SONAME.  
   This can be done by ensuring user will compile a shared library with a good unique (for
every version) SONAME or by runtime changing the SONAME in a (not yet loaded) library file.

   IMO the first one makes using Celix too complex and the second one is just too much hacking
for my taste. 
   
   So after loading, something like
   ```
   Bundle A  -- Export --> libfoo.so 1.0.0 [SONAME=libfoo.so.1.8.0]
   Bundle B  -- Export --> libfoo.so 2.0.0 [SONAME=libfoo.so.2.0.0]
   ```
   
   ## NEEDED 
   A bundle importing a library make this known by the NEEDED field (again a field of data
in a shared object file).
   This fields needs to be updated to the actual library imported. So a NEEDED with value
libfoo.so will need to transferred to a library reference with an actual version.
   
   In this case this cannot be done during compilation, because the whole point in that you
runtime import a library which matches your Import statement. So this must be done by updating
the NEEDED just before loading the bundle library. 
   And again IMO this is too complex and too much hacking. 
   
   So after loading, something like
   ```
   Bundle C <- Import --- libfoo.so [1,2)  [NEEDED=libfoo.so.1.8.0]
   Bundle D <- Import --- libfoo.so [2,3) [NEEDED=libfoo.so.2.0.0]
   ```
   
   # dlmopen to the rescue
   A few years ago (I think 3) dlmopen was added to GNU libc (linux!). If I read the documentation
correctly this should make it possible to create a load library namespace and load libraries
only into that namespace.
   Theoretically this should make it possible to create a library namespace for every bundle
and then "just" load libraries into the namespace and make exporting/importing possible that
way. 
   I did some experiments with this, but at that time dlmopen did not seem stable.
   
   Also dlmopen is only available for linux.
   
   # Is it worth it?
   All that being said. I am not sure if it is worth it. In my "day job" we do not use import/export
of library. 
   
   We do use LOCAL loading of private bundle libraries to be able to handle multiple versions
of libraries. But even for that use case, I am not sure if dynamic loading of libraries is
worth it.
   The reasons is that dynamic loading of libaries (in this case using bundles) make debugging
more diffcult. Especially when a) using different version of libraries with the same symbols
and b) post mortem analysing using a core dump. In the latter you need to somehow load the
bundle libraries again to get correct stacktraces.
   
   Al this in combination that we are moving to smaller executables running as docker/OCI
containers I think the whole module layer of OSGi is not worth it. But that just my opinion.

   And note that Celix is 'marketed' as a OSGI implementation in C and the module layer (including
import/export) is part of the OSGi spec.
   
   
   # Refactoring export/import and wiring
   Celix also has some implementation for the OSGi Capability Requirement Model.
   This part of the Celix has been very dormant for the last years and something I am not
really familiar with. 
   The whole Capability Requirement Model is tightly coupled with export/import support. So
if this is touched it would be good to revisit the wiring and resolving code of Celix (at
least ensure that the types get a celix_ prefix).  
   See 
   https://github.com/apache/celix/blob/master/libs/framework/include/wire.h
   https://github.com/apache/celix/blob/master/libs/framework/include/requirement.h
   https://github.com/apache/celix/blob/master/libs/framework/include/capability.h
   
   Sorry for this dump of information. 
   But I think it is smart to have a good discussion about this, before starting to code.
 
   
   
   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



Mime
View raw message