I've been working on <https://fedoraproject.org/wiki/Changes/Protobuf_5.x/6.x> and testing the packages in copr://mochaa/protobuf for the previous two years. It's unviable to package Protobuf and gRPC as shared libraries without introducing bugs in applications dependent on them.
1. Protobuf (and generally their consumers) doesn't account for multi-consumer-in-one-process situations when shared. Example: mozc, https://github.com/google/mozc/issues/387 `libmozc.so`, the input engine, initializes protobuf on start. Its `mozc_tool` executable, which doesn't depend on `libmozc.so` (and doesn't have a need to), also initializes protobuf on start. `mozc_tool` uses Qt, so `libmozc.so` will get loaded through the platform input plugin. This triggers a crash in `libprotobuf.so`, because it shares the global state between `dict_tool` and `libmozc.so`. `mozc_tool` and `libmozc.so` trying to register the same proto twice will fail the CHECK(). 2. gRPC depends on upb's internal global state. Although upb's document says it does not have global state, it crashes on tests if there are multiple definitions in different object files. This should be an ODR violation, but ASan & UBSan both report nothing in this case. Example A: https://github.com/grpc/grpc/issues/41613 By default, gRPC has its own build of upb with visibility=default and follows `BUILD_SHARED_LIBS`. However, Protobuf upstream says upb is not designed for shared library usage and forces you to build a static library with visibility=hidden. If we patch gRPC to use the system-provided static upb while building shared gRPC, different components as .so will link different copies of upb but still assume it's the same one. Example B: Although it was intended to be an internal dependency, gRPC's vendored upb build exports all symbols. If an application links to both gRPC and upb independently, symbols from one will take precedence over the other, depending on the order of the linker command line, and can crash the application because of the aforementioned reasons. There are possibly more quirks I didn't know. Alternative solutions I could think of are not viable: - Using the vendored copy of upb. This is prone to the problem in Example B. - Forcing upb to be built as a shared library with visibility=default. When multiple consumers link to the same upb.so in the same process, it may crash. - Building a shared upb with different symbol names (either through patchelf or a wrapper header) *could* do the job, but it relies on our own to make sure the behavior is the same as upstream. It will be needed to update every time if upstream changes the interface, which is very likely considering upb doesn't have a stable interface. - Provide shared by default, static as a subpackage. Not possible because the exported CMake targets can only be one of shared or static. This situation will likely not change because a) Google does not have a use for it. b) Can't afford API breakage. I'm also strongly against bundling those libraries due to the lack of tests. Running the test suite requires enormous setup but can ensure things weren't broken, especially on ppc64le and s390x. There are limitations to a shared library "by design", but mostly due to code that doesn't account for shared usage. Please leave your opinion about this. -- _______________________________________________ devel mailing list -- [email protected] To unsubscribe send an email to [email protected] Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/[email protected] Do not reply to spam, report it: https://forge.fedoraproject.org/infra/tickets/issues/new
