grpc: Unable to run grpcio wheel on alpine arvm7

What version of gRPC and what language are you using?

1.41.0 in python. Any grpcio release over 1.31.0 exhibits a variation on the problem.

What operating system (Linux, Windows,…) and version?

Linux arm32v7/alpine:3.12

What runtime / compiler are you using (e.g. python version or version of gcc)

Python 3.8.10 though other versions also show the same problem

What did you do?

Given an example Dockerfile like this:

FROM arm32v7/alpine:3.12

RUN apk add --no-cache python3 py3-pip
RUN apk add libstdc++ libc6-compat
RUN python3 --version

WORKDIR /code
COPY requirements.txt .
COPY example.py .

RUN pip3 install --no-cache-dir --only-binary=grpcio -r requirements.txt

CMD python3 ./example.py

Note that this also has problems finding the shared library without libstdc++ and libc6-compat but the errors has changed across grpc versions.

requirements.txt:

grpcio==1.41.0
google-cloud-pubsub

example.py

#!/usr/bin/python

from google.cloud import pubsub_v1

def main():
  print("Hello world")

if __name__ == "__main__":
  main()

Then run a build like this:

$ docker build --tag grpcio-armv7 .

What did you expect to see?

$ docker run grpcio-armv7
Hello world

Note, that this is what I see for alpine images on other architectures or different armv7 images like this:

FROM arm32v7/python:3.8-buster

What did you see instead?

$ docker run grpcio-armv7
Traceback (most recent call last):                                              
  File "./example.py", line 3, in <module>                                      
    from google.cloud import pubsub_v1                                          
  File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/__init__.py", li
ne 17, in <module>                                                              
    from google.cloud.pubsub_v1 import types                                    
  File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/types.py", line 
25, in <module>                                                                 
    from google.api_core import gapic_v1                                        
  File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/__init__.py", 
line 16, in <module>                                                            
    from google.api_core.gapic_v1 import config                                 
  File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/config.py", line 23, in <module>
    import grpc
  File "/usr/lib/python3.8/site-packages/grpc/__init__.py", line 22, in <module>
    from grpc import _compression
  File "/usr/lib/python3.8/site-packages/grpc/_compression.py", line 15, in <module>
    from grpc._cython import cygrpc
ImportError: Error relocating /usr/lib/python3.8/site-packages/grpc/_cython/cygrpc.cpython-38-arm-linux-gnueabihf.so: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7reserveEv: symbol not found

When using an older version of grpcio such as 1.38.X, I see an error message like:

Traceback (most recent call last):
  File "./example.py", line 3, in <module>
    from google.cloud import pubsub_v1
  File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/__init__.py", line 17, in <module>
    from google.cloud.pubsub_v1 import types
  File "/usr/lib/python3.8/site-packages/google/cloud/pubsub_v1/types.py", line 25, in <module>
    from google.api_core import gapic_v1
  File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/__init__.py", line 16, in <module>
    from google.api_core.gapic_v1 import config
  File "/usr/lib/python3.8/site-packages/google/api_core/gapic_v1/config.py", line 23, in <module>
    import grpc
  File "/usr/lib/python3.8/site-packages/grpc/__init__.py", line 23, in <module>
    from grpc._cython import cygrpc as _cygrpc
ImportError: Error relocating /usr/lib/python3.8/site-packages/grpc/_cython/cygrpc.cpython-38-arm-linux-gnueabihf.so: __strftime_l: symbol not found

This is similar to the first post of https://github.com/grpc/grpc/issues/24808 where the armv7 binary wheel has problems with alpine.

Anything else we should know about your project / environment?

This seems to have been an armv7 plus alpine issue that first happened last year. I have some history in https://github.com/home-assistant/core/issues/56669 though this was first seen with https://github.com/home-assistant/core/issues/40266 and https://github.com/home-assistant/core/issues/40148

Also note above that the Dockerfile explicitly adds libstdc++ libc6-compat which are not necessary for other platforms besides arvm7. Ideally that should not be needed and this could run on musl directly.

The discussion in https://github.com/grpc/grpc/issues/26620 seems quite relevant. Is building musllinux wheels for armv7 the right solution?

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 3
  • Comments: 26 (8 by maintainers)

Most upvoted comments

@lidizheng

Just came across this issue with grpcio on armhf on a musl based distro (alpine).

The root issue seems to be that grpc is publishing a vanilla wheel (non-manylinux or musllinux) for armhf on pypi, which is only meant for glibc based systems, but because it is not container based and is vanilla, thus named grpcio-1.43.0-cp39-cp39-linux_armv7l.whl, pip cannot really tell whether it is compatible with the musl based system or not. It happily installs it, but the installed package does not work. Therefore anyone doing pip install grpcio on an alpine armhf system will have a broken package.

The x86_64 and aarch64 versions are fine, because they are actually published as manylinux on pypi, which is properly recognized by pip as not compatible with a musl based system and therefore pip correctly compiles from source.

I think the proper solution would be for grpc to not publish a vanilla wheel like that on pypi, and only rely on manylinux and musllinux (container based) wheels on linux (no idea how it is on other platforms like windows).

I’m not aware of any other project on pypi that publishes vanilla wheels.

Thanks

PS. If you build these wheels via pip wheel on armhf on ubuntu (glibc) and alpine (musl), both systems will produce wheels named grpcio-1.43.0-cp39-cp39-linux_armv7l.whl and pip cannot distinguish between the two, but they won’t be compatible with each other. That’s why it’s best for official wheels on pypi to be container based as pip is aware of their compatibility and doesn’t incorrectly use them on the wrong system.

We, at linuxserver.io, publish various vanilla wheels in our repos for reuse in our docker images, but in order to overcome the above mentioned issue, we keep glibc and musl based wheels in separate endpoints: https://wheel-index.linuxserver.io/ To complicate matters further, vanilla wheels also suffer from incompatibility due to system dependency package versions. For instance alpine 3.14 and 3.15 both have python 3.9 so pip thinks their vanilla wheels are compatible, but cffi for instance uses a shared library of libffi. If the cffi wheel is built on alpine 3.14, it is linked to libffi 7, but when it’s used on alpine 3.15, it fails because 3.15 contains libffi 8. We can get away with maintaining separate repos for glibc vs musl, and different distro versions, because we can define different repos in our docker images, however for publishing on pypi, which is a single universal repo, the solution is to ship container based wheels with proper compatibility and with statically linked deps.

EDIT2: I should clarify that my above comments apply to cpython wheels. Pure python wheels (*-pyX-none-any.whl) are not glibc or musl dependent so they can be published as is on pypi with no issues.

I was able to get an armv7 alpine wheel built for home assistant (codified here https://github.com/allenporter/wheels-grpc)

However, that wheel doesn’t work on a plain Alpine install either and fails with the same error as the wheel built from grpc source. I think the hole assistant is building python from source and may be patching it in some way.
However my immediate user need is solved for the moment and we’ve been able to move to the latest grpc for the next release.

More investigation is needed here for a grpc built wheel that works on Alpine armv7

OK – I had problems finding audithweel for the musl architecture and had to disable it, so that makes sense. However, i’m having the cygrpc problem on both architectures so perhaps i’ll focus there first.

This is the same problem in https://github.com/grpc/grpc/issues/26094 so I included a repro case there.

Issue also happening running through Bazel on Apple M1.