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

Unable to load shared library 'pact_ffi' or one of its dependencies #387

Closed
chertby opened this issue Apr 25, 2022 · 17 comments · May be fixed by #502
Closed

Unable to load shared library 'pact_ffi' or one of its dependencies #387

chertby opened this issue Apr 25, 2022 · 17 comments · May be fixed by #502

Comments

@chertby
Copy link

chertby commented Apr 25, 2022

Hello.
I have an issue with the current PactNet Beta version (4.0.0-beta.3) in the CI pipeline.

Error Message:
   System.DllNotFoundException : Unable to load shared library 'pact_ffi' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: Error loading shared library libpact_ffi: No such file or directory

Next, I tried to run the tests in docker with the mcr.microsoft.com/dotnet/sdk:6.0 image and the tests runed successful.

After that, I changed the image to mcr.microsoft.com/dotnet/sdk:6.0-alpine and got the following error:

Error Message:
   System.DllNotFoundException : Unable to load shared library 'pact_ffi' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: Error loading shared library libpact_ffi: No such file or directory
  Stack Trace:
     at PactNet.Interop.NativeInterop.LogToBuffer(LevelFilter levelFilter)
   at PactNet.Verifier.InteropVerifierProvider.Initialise()
   at PactNet.Verifier.PactVerifier.InitialiseProvider(String providerName, Uri pactUri)
   at PactNet.Verifier.PactVerifier.ServiceProvider(String providerName, Uri pactUri)

What additional information to provide to correct the issue?

@mefellows
Copy link
Member

That suggests the library pact_ffi wasn't installed or does not match your architecture.

The error message describes the next course of action - can you please follow those instructions and paste here?

Also your OS/Architecture and .NET version would probably help.

@adamrodger should we setup an issue template here?
@YOU54F we should probably make this consistent (to the degree that makes sense) across the ecosystem.

@YOU54F
Copy link
Member

YOU54F commented Apr 25, 2022

agreed, I love docusurus's

https://github.com/facebook/docusaurus/issues/new/choose

it makes it easier than the commented text that takes up all the space when you want to raise an issue, and I find it easier just to get rid of it all and start my own way. That template above once you click on an option, gives you discreet sections/checklists etc.

Some could be consistent for routine pact checks, and we could have library specific sections.

@YOU54F
Copy link
Member

YOU54F commented Apr 25, 2022

everything is more awkward with alpine @chertby as many required dependencies for simple programs aren't available.

I've often found debian stretch images to be a better starting point as by the time you've got thing you need in alpine, you end up with a much bigger image, and have had a huge time sink to boot

@YOU54F
Copy link
Member

YOU54F commented Apr 25, 2022

We do have some instructions for alpine on linux with the ruby core

https://docs.pact.io/docker#alpine-linux

@chertby if you sort it, we would appreciate you updating the documentation or providing steps for others.

@mefellows
Copy link
Member

After that, I changed the image to mcr.microsoft.com/dotnet/sdk:6.0-alpine and got the following error:

ah, I don't believe Alpine is supported - see #374.

As per the issue, we can't test it reliably yet.

@chertby
Copy link
Author

chertby commented Apr 27, 2022

Are there any plans to support Alpine in version 4.0, maybe I can be of some help to you and try to implement it?

@mefellows
Copy link
Member

Yes, we'd like to be able to support Alpine, albeit have a read through the issues linked above to see the current challenges. There is a musl build being published, but we don't have a reliable and repeatable process for testing it here.

@adamrodger
Copy link
Contributor

adamrodger commented Apr 29, 2022 via email

@mefellows
Copy link
Member

Yeah, Rust wanted to create a static archive for musl. I believe there is a flag that can be used to compile it into a shared lib, so that's worth experimenting with.

@uglyog
Copy link
Member

uglyog commented May 1, 2022

While it is technically possible to create a dynamically linked library for Alpine, it is not advisable to do so. In essence, what you are creating is a shared library with the musl C library statically linked into it. What this means, if you then try to use this library on a different version of Alpine/musl, it can result in corruption of thread state and segmentation violations.

Dynamically linked libraries will have to be built for each specific version of Alpine and musl, and I don't see the benefit in maintaining that. If people what this, I would recommend using Debian based docker images which support dynamically linked glibc.

@mefellows
Copy link
Member

Got it, makes sense Ron.

Our current docker advice will need updating once the v3 is the major player, else we'll end up confusing people.

@adamrodger
Copy link
Contributor

Closing as the FFI lib doesn't support Alpine currently (and may never properly) and so PactNet can't either. We can reopen if the FFI situation changes

@YOU54F
Copy link
Member

YOU54F commented May 3, 2022

Got it, makes sense Ron.

Our current docker advice will need updating once the v3 is the major player, else we'll end up confusing people.

Good shout @mefellows and thanks for the sage advice @uglyog

I’ll add it to the list, would be worth adding that advice anyway. I’ve always used and recommended debian stretch for a lightweight image that doesn’t involve the associated complications of alpine, for a few mb’s.

@reetu
Copy link

reetu commented Dec 15, 2022

We do have some instructions for alpine on linux with the ruby core

https://docs.pact.io/docker#alpine-linux

@chertby if you sort it, we would appreciate you updating the documentation or providing steps for others.

I was able to get Pact3 going on alpine-node:16 🎉 .

This approach blows up the image size considerably, but it's useful in my current situation where we use alpine for local testing only, not deployment. I also tried using gcompat, the glibc-muscl compatibility lib without success.

You will need to install ca-certificates, g++, glibc, make, wget and python3 on your alpine image:

RUN apk add --no-cache \
      ca-certificates  \
      g++ \
      make \
      wget

# Install glibc
RUN wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
RUN wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk
RUN apk add glibc-2.28-r0.apk

# Install python3
ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python
RUN python3 -m ensurepip
RUN pip3 install --no-cache --upgrade pip setuptools

@mefellows
Copy link
Member

Hi Reetu, glad to see you got it working. I will just add a reminder that (as per Ron's comments above) it's highly likely you will eventually run into issues on Alpine with that setup. We don't officially support that setup, so please do note that if you do run into issues.

@reetu
Copy link

reetu commented Dec 21, 2022

Noted. We did end up running into weird problems on different environments (fine on Mac M1, failed on Ubuntu) so we're trying a multi-stage docker build with alpine-node:16 and pact-js-musl:16 instead. I'll let you know how it goes.

@drakulavich
Copy link

If you want to install pact during docker build consider adding the following dependencies for Alpine:

RUN apk add --no-cache libc6-compat python3 make g++

That's our workaround to build a front-end app.

YOU54F added a commit to YOU54F/pact-net that referenced this issue May 29, 2024
## Rationale

pact-reference has introduced musl and arm64 based ffi libraries for linux

- pact-foundation/pact-reference#416

Tracking Issue

- pact-foundation/roadmap#30

## Issues Resolved

fixes pact-foundation#498
fixes pact-foundation#496
fixes pact-foundation#500
fixes pact-foundation#374
fixes pact-foundation#387

## Backwards Compatibility

Linux glibc based hosts take precedence, so if any error occurs during musl
detection. I do not anticipate breaking changes for users

## Implementation notes

### .NET notes

- Docs
  - [Uses MSBuild Exec task](https://learn.microsoft.com/en-us/visualstudio/msbuild/exec-task?view=vs-2022)
- MSBuild Blog Posts
  - [Cross-Platform Build Events in .NET Core using MSBuild](https://jeremybytes.blogspot.com/2020/05/cross-platform-build-events-in-net-core.html)
  - [MSBuild 101: Using the exit code from a command](https://www.creepingcoder.com/2020/06/01/msbuild-101-using-the-exit-code-from-a-command/)
- Stack OverFlow
  - [Set PropertyGroup property to Exec output](https://stackoverflow.com/questions/76583824/set-propertygroup-property-to-exec-output)
- .NET runtime musl detection code
  - https://github.com/dotnet/runtime/blob/a50ba0669353893ca8ade8568b0a7d210b5a425f/src/mono/llvm/llvm-init.proj\#L7
  - https://github.com/dotnet/runtime/blob/a50ba0669353893ca8ade8568b0a7d210b5a425f/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs\#L78t

### Conditions for execution

musl detection will run if

- if linux
- if /lib/ld-musl-(x86_64|aarch64).so.1 exists
- if ldd bin/sh | grep musl is true (musl lib is loaded, rather than glibc)

will continue on error, reverting back to glibc based libaries.

### Supported musl targets

should work for multiple musl based distroes if

- /lib/ld-musl-(x86_64|aarch64).so.1 exists
- ldd is available (available by default in alpine images)

Tested on Alpine ARM64 / AMD64.

## Caveats

- [.NET does not run under QEMU](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md#qemu) affecting the ability to test multi-arch from a single system
- .NET restore can take a long time when running under containers.
  - [Workaround](NuGet/Home#13062 (comment)): Set `DOTNET_NUGET_SIGNATURE_VERIFICATION` to `false`

## Compatibility

### Operating System

Due to using a shared native library instead of C# for the main Pact logic only certain OSs are supported:

| OS           | Arch        | Support                                                            |
| ------------ | ----------- | -------------------------------------------------------------------|
| Windows      | x86         | ❌ No                                                              |
| Windows      | x64         | ✔️ Yes                                                              |
| Linux (libc) | x86         | ❌ No                                                              |
| Linux (libc) | x64         | ✔️ Yes                                                              |
| Linux (musl) | x64         | ✔️ Yes (Tier 2)*                                                    |
| Linux (libc) | ARM         | ✔️ Yes (Tier 3)*                                                    |
| Linux (musl) | ARM         | ✔️ Yes (Tier 3)*                                                    |
| OSX          | x64         | ✔️ Yes                                                              |
| OSX          | ARM (M1/M2) | ✔️ Yes                                                              |

#### Support

- Tier 1
  - Established
  - Full CI/CD support.
  - Users should not encounter issues
  - Full reproducible examples running in CI, should be provided by users raising issues
  - If using musl targets, users should attempt the same test on a libc target (such as debian)
- Tier 2
  - Recently introduced
  - Full CI/CD support.
  - Users may encounter issues
  - Full reproducible examples running in CI, should be provided by users raising issues
  - If using musl targets, users should attempt the same test on a libc target (such as debian)
- Tier 3
  - Recently introduced, No/limited CI/CD support.
  - Users may encounter issues
  - Full reproducible examples which can be run by maintainers locally, should be provided by users raising issues
YOU54F added a commit to YOU54F/pact-net that referenced this issue Sep 24, 2024
## Rationale

pact-reference has introduced musl and arm64 based ffi libraries for linux

- pact-foundation/pact-reference#416

Tracking Issue

- pact-foundation/roadmap#30

## Issues Resolved

fixes pact-foundation#498
fixes pact-foundation#496
fixes pact-foundation#500
fixes pact-foundation#374
fixes pact-foundation#387

## Backwards Compatibility

Linux glibc based hosts take precedence, so if any error occurs during musl
detection. I do not anticipate breaking changes for users

## Implementation notes

### .NET notes

- Docs
  - [Uses MSBuild Exec task](https://learn.microsoft.com/en-us/visualstudio/msbuild/exec-task?view=vs-2022)
- MSBuild Blog Posts
  - [Cross-Platform Build Events in .NET Core using MSBuild](https://jeremybytes.blogspot.com/2020/05/cross-platform-build-events-in-net-core.html)
  - [MSBuild 101: Using the exit code from a command](https://www.creepingcoder.com/2020/06/01/msbuild-101-using-the-exit-code-from-a-command/)
- Stack OverFlow
  - [Set PropertyGroup property to Exec output](https://stackoverflow.com/questions/76583824/set-propertygroup-property-to-exec-output)
- .NET runtime musl detection code
  - https://github.com/dotnet/runtime/blob/a50ba0669353893ca8ade8568b0a7d210b5a425f/src/mono/llvm/llvm-init.proj\#L7
  - https://github.com/dotnet/runtime/blob/a50ba0669353893ca8ade8568b0a7d210b5a425f/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs\#L78t

### Conditions for execution

musl detection will run if

- if linux
- if /lib/ld-musl-(x86_64|aarch64).so.1 exists
- if ldd bin/sh | grep musl is true (musl lib is loaded, rather than glibc)

will continue on error, reverting back to glibc based libaries.

### Supported musl targets

should work for multiple musl based distroes if

- /lib/ld-musl-(x86_64|aarch64).so.1 exists
- ldd is available (available by default in alpine images)

Tested on Alpine ARM64 / AMD64.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants