snappy-java icon indicating copy to clipboard operation
snappy-java copied to clipboard

Snappy native library static initialization error on Alpine Linux with jdk17

Open mmopenet opened this issue 1 year ago • 1 comments

The snappy native library terminates with abort signal during initialization with the following error:

terminate called after throwing an instance of '__gnu_cxx::recursive_init_error'
  what():  std::exception

The problem occurs on Alpine Linux 3.20.3 with openjdk17 package installed. I have also verified that it does not happen with the openjdk8 with the same Alpine Linux image. On Ubuntu 20 and 22 the problem does not occur in both jdk8 and jdk17.

The abort seems to be triggered from initialization of static local variable here https://github.com/google/snappy/blob/main/snappy.cc#L401.

What I have noted is that Alpine package openjdk17 does not depend on the libstdc++.so and the JVM process does not load it. This means that the call to __cxa_guard_acquire is dynamically resolved to statically linked version of this function in libsnappyjava.so, which does not appear to be thread-safe. In all other cases I have tried (jdk8 and jdk17 on Ubuntu) the libstdc++.so is loaded by the JVM, and the __cxa_guard_acquire is resolved to the version in libstdc++.so, which seems to be thread-safe.

To reproduce the issue run bellow java program with snappy-java-1.1.10.7.jar and openjdk17 on Alpine Linux 3.20.3. The problem occurs in about 1 of 10 runs.

import java.util.ArrayList;
import org.xerial.snappy.Snappy;

public class Test {

	static volatile long startTime;
	static byte[] compressed;

	public static void main(String[] args) throws Exception {

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < 2701; ++i) {
			sb.append(".");
		}
		String data = sb.toString();
		compressed = Snappy.compress(data);
		startTime = System.nanoTime() + 100_000_000;
		ArrayList<Thread> threads = new ArrayList<Thread>();
		for (int i = 0; i < 4; i++) {
			Thread t = new Thread(new Runnable() {
				public void run() {
					while (System.nanoTime() < startTime) {
					}
					try {
						byte[] uncompressed = Snappy.uncompress(compressed);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
			threads.add(t);
			t.start();
		}
		for (Thread t : threads) {
			t.join();
		}
	}
}

mmopenet avatar Nov 20 '24 13:11 mmopenet

Is there any workaround for this issue?

vepo avatar Jan 16 '25 14:01 vepo

Seems this issue has been addressed by https://github.com/xerial/snappy-java/pull/632

I tested the provided code in openjdk:17-jdk-alpine, it fails with snappy-java-1.1.10.7.jar and works well with snappy-java-1.1.10.8.jar

pan3793 avatar Jul 21 '25 14:07 pan3793

I have tested the with v1.1.10.8 and it works for me.

mmopenet avatar Jul 24 '25 12:07 mmopenet