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
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