Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nativeaccess: try to load all located libsystemds #108238

Merged
merged 9 commits into from
May 8, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/changelog/108238.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 108238
summary: "Nativeaccess: try to load all located libsystemds"
area: Infra/Core
type: bug
issues:
- 107878
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import java.lang.foreign.MemorySegment;
import java.lang.invoke.MethodHandle;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.JAVA_INT;
Expand All @@ -26,31 +29,49 @@
class JdkSystemdLibrary implements SystemdLibrary {

static {
System.load(findLibSystemd());
}

// On some systems libsystemd does not have a non-versioned symlink. System.loadLibrary only knows how to find
// non-versioned library files. So we must manually check the library path to find what we need.
static String findLibSystemd() {
final String libsystemd = "libsystemd.so.0";
String libpath = System.getProperty("java.library.path");
for (String basepathStr : libpath.split(":")) {
var basepath = Paths.get(basepathStr);
if (Files.exists(basepath) == false) {
continue;
// Find and load libsystemd. We attempt all instances of
// libsystemd in case of multiarch systems, and stop when
// one is successfully loaded. If none can be loaded,
// UnsatisfiedLinkError will be thrown.
List<String> paths = findLibSystemd();
if (paths.isEmpty()) {
String libpath = System.getProperty("java.library.path");
throw new UnsatisfiedLinkError("Could not find libsystemd in java.library.path: " + libpath);
}
UnsatisfiedLinkError last = null;
for (String path : paths) {
try {
System.load(path);
last = null;
break;
} catch (UnsatisfiedLinkError e) {
last = e;
}
try (var stream = Files.walk(basepath)) {
}
if (last != null) {
throw last;
}
}

var foundpath = stream.filter(Files::isDirectory).map(p -> p.resolve(libsystemd)).filter(Files::exists).findAny();
if (foundpath.isPresent()) {
return foundpath.get().toAbsolutePath().toString();
}
// findLibSystemd returns a list of paths to instances of libsystemd
// found within java.library.path.
static List<String> findLibSystemd() {
// Note: on some systems libsystemd does not have a non-versioned symlink.
// System.loadLibrary only knows how to find non-versioned library files,
// so we must manually check the library path to find what we need.
final Path libsystemd = Paths.get("libsystemd.so.0");
final String libpath = System.getProperty("java.library.path");
return Arrays.stream(libpath.split(":")).map(Paths::get).filter(Files::exists).flatMap(p -> {
try {
return Files.find(
p,
Integer.MAX_VALUE,
(fp, attrs) -> (attrs.isDirectory() == false && fp.getFileName().equals(libsystemd))
);
} catch (IOException e) {
throw new UncheckedIOException(e);
}

}
throw new UnsatisfiedLinkError("Could not find " + libsystemd + " in java.library.path: " + libpath);
}).map(p -> p.toAbsolutePath().toString()).toList();
}

private static final MethodHandle sd_notify$mh = downcallHandle("sd_notify", FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS));
Expand Down