Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,46 @@ jobs:
./sbt test
- name: JAR Integration Test
run: ./script/test-jar-integration.sh
test-musl:
strategy:
matrix:
include:
# musl-based JVM: the x86_64-musl native library must be used
- name: alpine
container: eclipse-temurin:17-jdk-alpine
expected_arch: x86_64-musl
# glibc-based JVM with musl also installed (#692): the glibc native library must be used
- name: glibc with musl installed
container: ''
expected_arch: x86_64
name: test ${{ matrix.name }}
needs: changes
if: ${{ needs.changes.outputs.code == 'true' }}
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- name: Install packages (alpine)
if: ${{ matrix.container != '' }}
run: apk add --no-cache bash curl git
- uses: actions/checkout@v6
- uses: actions/setup-java@v5
if: ${{ matrix.container == '' }}
with:
distribution: 'zulu'
java-version: '17'
- name: Install musl
if: ${{ matrix.container == '' }}
run: |
sudo apt-get update
sudo apt-get install -y musl
ls -l /lib/ld-musl-x86_64.so.1
- name: Check native library architecture
shell: bash
run: |
./sbt compile
arch=$(java -cp target/classes org.xerial.snappy.OSInfo --arch)
echo "detected arch: $arch"
test "$arch" = "${{ matrix.expected_arch }}"
- name: Test
shell: bash
run: ./sbt test
39 changes: 34 additions & 5 deletions src/main/java/org/xerial/snappy/OSInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
//--------------------------------------
package org.xerial.snappy;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
Expand Down Expand Up @@ -220,7 +221,7 @@ public static String getArchName() {
return "android-arm";
}

if (isX64Musl()) {
if (isX64Musl(osArch)) {
return "x86_64-musl";
}

Expand All @@ -235,10 +236,38 @@ public static String getArchName() {
return translateArchNameToFolderName(osArch);
}

private static boolean isX64Musl() {
private static boolean isX64Musl(String osArch) {
String lc = osArch == null ? "" : osArch.toLowerCase(Locale.US);
if (!System.getProperty("os.name", "").contains("Linux") || !"x86_64".equals(archMapping.get(lc))) {
return false;
}
// Check the C library actually loaded into this JVM process. Testing for the presence of
// /lib/ld-musl-x86_64.so.1 is not enough, since musl can be installed on glibc-based systems
// (e.g., as a dependency of other software), where the musl build of the native library fails to load.
return isMuslLoaded("/proc/self/maps");
}

static boolean isMuslLoaded(String mapsFile) {
try {
return new File("/lib/ld-musl-x86_64.so.1").exists();
} catch (SecurityException e) {
BufferedReader reader = new BufferedReader(new FileReader(mapsFile));
try {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("/ld-musl-") || line.contains("/libc.musl-")) {
return true;
}
}
return false;
}
finally {
reader.close();
}
}
catch (IOException e) {
// /proc is unavailable: fall back to the glibc build
return false;
}
catch (SecurityException e) {
return false;
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/test/java/org/xerial/snappy/OSInfoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import static org.junit.Assert.*;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintStream;

import org.junit.Test;
Expand Down Expand Up @@ -112,4 +114,35 @@ public void testMainForArchName()
System.setOut(out);
}
}

private static File writeMaps(String content)
throws Exception
{
File f = File.createTempFile("snappy-maps", ".txt");
f.deleteOnExit();
FileWriter w = new FileWriter(f);
try {
w.write(content);
}
finally {
w.close();
}
return f;
}

// https://github.com/xerial/snappy-java/issues/692
@Test
public void detectMuslFromProcessMaps()
throws Exception
{
File musl = writeMaps("7f0000000000-7f0000001000 r-xp 00000000 08:01 123 /lib/ld-musl-x86_64.so.1\n");
assertTrue(OSInfo.isMuslLoaded(musl.getPath()));

// glibc process on a system that also has musl installed
File glibc = writeMaps("7f0000000000-7f0000001000 r-xp 00000000 08:01 123 /usr/lib/x86_64-linux-gnu/libc.so.6\n"
+ "7f0000002000-7f0000003000 r-xp 00000000 08:01 456 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2\n");
assertFalse(OSInfo.isMuslLoaded(glibc.getPath()));

assertFalse(OSInfo.isMuslLoaded("/non-existent/maps"));
}
}
Loading