Commit d43f9678 authored by Kunshan Wang's avatar Kunshan Wang

Work around premature dylib close.

parent 88bba067
package com.kenai.jffi;
/**
* Work-around the problem that com.kenai.jffi.Library sometimes get prematurely
* finalized. So we open and close libs without relying on GC.
*/
public class ForeignThief {
public static final int LAZY = Foreign.RTLD_LAZY;
public static final int NOW = Foreign.RTLD_NOW;
public static final int LOCAL = Foreign.RTLD_LOCAL;
public static final int GLOBAL = Foreign.RTLD_GLOBAL;
public static long dlopen(String name, int flags) {
return Foreign.dlopen(name, flags);
}
public static void dlclose(long handle) {
Foreign.dlclose(handle);
}
public static long dlsym(long handle, String name) {
return Foreign.dlsym(handle, name);
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ package uvm.refimpl.nat
import scala.collection.mutable.ArrayBuffer
import com.kenai.jffi.Library
import com.kenai.jffi.ForeignThief
import uvm.refimpl.UvmExternalLibraryException
......@@ -23,17 +23,35 @@ object NativeLibraryHolder {
}
}
class ManualLibrary(val handle: Long) extends AutoCloseable {
def getSymbolAddress(symbol: String): Long = {
ForeignThief.dlsym(handle, symbol)
}
override def close(): Unit = {
if (handle != 0L) {
ForeignThief.dlclose(handle)
}
}
}
/**
* A holder of jffi Library instances. It can find symbols from all loaded libraries.
*/
class NativeLibraryHolder() {
val libs = new ArrayBuffer[Library]()
class NativeLibraryHolder() extends AutoCloseable {
val libs = new ArrayBuffer[ManualLibrary]()
override def close(): Unit = {
for (lib <- libs) {
lib.close()
}
}
/**
* Load the default library: the current process.
*/
def loadDefaultLibrary(): Library = {
val lib = Library.getDefault()
def loadDefaultLibrary(): ManualLibrary = {
val handle = ForeignThief.dlopen(null, ForeignThief.NOW)
val lib = new ManualLibrary(handle)
libs += lib
lib
}
......@@ -43,13 +61,14 @@ class NativeLibraryHolder() {
*
* @param path the path. eSee the man page of dlopen for the path format.
*/
def loadLibrary(path: String): Library = {
val lib = Option(Library.openLibrary(path, Library.NOW))
lib match {
def loadLibrary(path: String): ManualLibrary = {
val maybeHandle = Option(ForeignThief.dlopen(path, ForeignThief.NOW))
maybeHandle match {
case None => throw new UvmExternalLibraryException("Cannot load library: %s".format(path))
case Some(l) =>
libs += l
l
case Some(handle) =>
val lib = new ManualLibrary(handle)
libs += lib
lib
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment