-
Notifications
You must be signed in to change notification settings - Fork 249
Description
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();
}
}
}