Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise an Unhandled Exception: System.TypeInitializationException when I run example #97

Closed
Nickiven opened this issue Apr 12, 2023 · 6 comments · Fixed by #98
Closed

Comments

@Nickiven
Copy link

Nickiven commented Apr 12, 2023

Ubuntu 22.04
ROS2 humble
.net runtime 6.0
I followed guide and launched example, then I get an exception as below:
image
Please help. thanks~

@hoffmann-stefan
Copy link
Member

hoffmann-stefan commented Apr 15, 2023

Hi @Nickiven, thanks for reporting the bug. Would have stumbled upon this myself when upgrading to humble/Ubuntu 22.04 as well. But now I know ahead of time :)

Was able to reproduce this locally using this Dockerfile.

Seems to be related to the use of libdl.so but libdl.so.2 should be used instead, see this stackoverflow answer: https://stackoverflow.com/a/75855054

Found another dotnet library having the same issue here: ied206/Joveler.DynLoader#1

The fix should be to replace all occurrences of libdl.so with libdl.so.2 in rcldotnet_common/DllLoadUtils.cs:

diff --git a/rcldotnet_common/DllLoadUtils.cs b/rcldotnet_common/DllLoadUtils.cs
index 280ca65..6aff8e3 100644
--- a/rcldotnet_common/DllLoadUtils.cs
+++ b/rcldotnet_common/DllLoadUtils.cs
@@ -54,10 +54,10 @@ namespace ROS2 {
       [DllImport ("kernel32.dll", EntryPoint = "FreeLibrary", SetLastError = true, ExactSpelling = true)]
       private static extern int FreeLibraryDesktop (IntPtr handle);
 
-      [DllImport ("libdl.so", EntryPoint = "dlopen")]
+      [DllImport ("libdl.so.2", EntryPoint = "dlopen")]
       private static extern IntPtr dlopen_unix (String fileName, int flags);
 
-      [DllImport ("libdl.so", EntryPoint = "dlclose")]
+      [DllImport ("libdl.so.2", EntryPoint = "dlclose")]
       private static extern int dlclose_unix (IntPtr handle);
 
       [DllImport ("libdl.dylib", EntryPoint = "dlopen")]
@@ -106,7 +106,7 @@ namespace ROS2 {
 
       private static bool IsUnix () {
         try {
-          IntPtr ptr = dlopen_unix ("libdl.so", RTLD_NOW);
+          IntPtr ptr = dlopen_unix ("libdl.so.2", RTLD_NOW);
           dlclose_unix (ptr);
           return true;
         } catch (TypeLoadException) {
@@ -205,16 +205,16 @@ namespace ROS2 {
 
     internal class DllLoadUtilsUnix : DllLoadUtils {
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern IntPtr dlopen (String fileName, int flags);
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern IntPtr dlsym (IntPtr handle, String symbol);
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern int dlclose (IntPtr handle);
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern IntPtr dlerror ();
 
       const int RTLD_NOW = 2;

Could you test this quick fix on your side and look if it would work? Did so at least for me in the docker image.

@hoffmann-stefan hoffmann-stefan linked a pull request Apr 16, 2023 that will close this issue
1 task
@hoffmann-stefan
Copy link
Member

Could reproduce the issue in CI too:

@Nickiven could you take a look at this PR and test if it works for you? Would you mind doing a quick review on GitHub as well, but no presure :)

@Nickiven
Copy link
Author

Hi @Nickiven, thanks for reporting the bug. Would have stumbled upon this myself when upgrading to humble/Ubuntu 22.04 as well. But now I know ahead of time :)

Was able to reproduce this locally using this Dockerfile.

Seems to be related to the use of libdl.so but libdl.so.2 should be used instead, see this stackoverflow answer: https://stackoverflow.com/a/75855054

Found another dotnet library having the same issue here: ied206/Joveler.DynLoader#1

The fix should be to replace all occurrences of libdl.so with libdl.so.2 in rcldotnet_common/DllLoadUtils.cs:

diff --git a/rcldotnet_common/DllLoadUtils.cs b/rcldotnet_common/DllLoadUtils.cs
index 280ca65..6aff8e3 100644
--- a/rcldotnet_common/DllLoadUtils.cs
+++ b/rcldotnet_common/DllLoadUtils.cs
@@ -54,10 +54,10 @@ namespace ROS2 {
       [DllImport ("kernel32.dll", EntryPoint = "FreeLibrary", SetLastError = true, ExactSpelling = true)]
       private static extern int FreeLibraryDesktop (IntPtr handle);
 
-      [DllImport ("libdl.so", EntryPoint = "dlopen")]
+      [DllImport ("libdl.so.2", EntryPoint = "dlopen")]
       private static extern IntPtr dlopen_unix (String fileName, int flags);
 
-      [DllImport ("libdl.so", EntryPoint = "dlclose")]
+      [DllImport ("libdl.so.2", EntryPoint = "dlclose")]
       private static extern int dlclose_unix (IntPtr handle);
 
       [DllImport ("libdl.dylib", EntryPoint = "dlopen")]
@@ -106,7 +106,7 @@ namespace ROS2 {
 
       private static bool IsUnix () {
         try {
-          IntPtr ptr = dlopen_unix ("libdl.so", RTLD_NOW);
+          IntPtr ptr = dlopen_unix ("libdl.so.2", RTLD_NOW);
           dlclose_unix (ptr);
           return true;
         } catch (TypeLoadException) {
@@ -205,16 +205,16 @@ namespace ROS2 {
 
     internal class DllLoadUtilsUnix : DllLoadUtils {
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern IntPtr dlopen (String fileName, int flags);
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern IntPtr dlsym (IntPtr handle, String symbol);
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern int dlclose (IntPtr handle);
 
-      [DllImport ("libdl.so", ExactSpelling = true)]
+      [DllImport ("libdl.so.2", ExactSpelling = true)]
       private static extern IntPtr dlerror ();
 
       const int RTLD_NOW = 2;

Could you test this quick fix on your side and look if it would work? Did so at least for me in the docker image.

Hi Stefan,

Thanks for your quick response!
I have followed your guide and modified the DllLoadUtils.cs manually. After rebuilding, it's working now! Super! And I have checked the PR as well.
image

I have one more question, is it possible that I can add these references to my own project such as console or .NET core webAPI to create ROS2 node? I have noticed that these dlls can be used in the UWP project in the ReadMe document.

Thank you!

Nick

@hoffmann-stefan
Copy link
Member

@Nickiven I'm not familiar with the UWP part of the readme. Did a quick read, my initial reaction would be to not include the ddl's from the working directory in an external project (one outside a ROS workspace) like described here. This may be the only way for UWP/Visual Studio/Unity that works right now, but on Linux or Windows Desktop with "modern" .NET I would start the build from the command line inside a ROS workspace.

The thing is that the dotnet dll's need to load native libraries that are provided by sourcing the workspace as well. Getting to include those ddl's from a standard .NET project external to a ROS workspace might not be that easy (though I haven't looked into this in detail).

I would make the executable node part of the ROS workspace. From there on you have some ways of doing things:

  • Have everything build as a ROS package inside a workspace
    • Either only use CMakeLists.txt as Project file and let cmake generate a *.csproj as part of the build.
      • There you have the least amout of configurability in the *.csproj file, but references to other ROS packages and NuGet packages work if that is enought. Tough for ASP.NET Core projects you need to switch the SDK in the project file, not sure if this is possible out of my head right now.
    • Or use our (@schiller-de) internal branch to include normal *.csproj files in a CmakeLists.txt for building, this works quite well if you are used to that project format and wan't to configure other dotnet project properties as well. It is not upstreamed tough right now, see last section on this comment: How to add reference to external dlls in cmakelist  #95 (comment)
      • There you can defenetly use ASP.NET Core, that's how we do this.
  • Have only a minimal ROS package inside a workspace like described in the bullet above and consume other external code via NuGet packages. Those external packages can't reference the ROS messages or rcldotnet though.

I hope this are some pointers how this could work for you. Unfortunately this isn't realy documented in a nice way with some example projects yet. Maybe I get to create some example projects this week, as you are the second one to ask for this the last two months, but can't promise anything. Maybe if you get something working could you share samples for others as well?

@Nickiven
Copy link
Author

@hoffmann-stefan Very appreciate for your quick response. I think your answer will helps me a lot. I'll keep working on this. If I have any progress, I will share it here ASAP.
Nick

@hoffmann-stefan
Copy link
Member

@Nickiven Glad to hear :)

Some other note as you seem to work actively with ros2_dotnet and I don't know if you noticed this:
I merged two of my long standing PRs right now that somewat break the API, but add Service/Client support, better Excpeption handling and make the naming convention for the generated message classes more .NET like:

So you might check the current master branch out.
Sorry for the inconvenience of breaking the API, but better early than late ;)

And if you have interest in a TF2 implementation see https://github.com/schiller-de/tf2_dotnet, though this requires not already merged changes, but you can check them out in #94. The later PR should get split up and merged the next weeks. Would be pleased if you could do some reviews as this happens :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants