Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory issues while loading two native libraries containing same symbols

I'm trying to operate a native, non-thread-safe Fortran library concurrently using JNA. As the library is not thread-safe, I try to instantiate different copies of the same library, but apparently they seem to share memory addresses. If I modify one variable in one library, the variable in the other library is modified to. This behavior makes it impossible to run them concurently in separate threads.

The following code example demonstrates what I mean:

code.f:

  subroutine set(var)
     implicit none
     integer var,n
     common/conc/n
     n=var
  end subroutine

  subroutine get(var)
     implicit none
     integer var,n
     common/conc/n
     var=n
  end subroutine

This file is compiled and copied as follows:

gfortran -shared -O2 code.f -o mylib.so -fPIC
cp mylib.so mylib_copy.so

Then I access those two using JNA:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;

public class JNA {
    public interface MyLib extends Library {
        public void set_(IntByReference var);
        public void get_(IntByReference var);
    }

    public static void main(String[] args) {
        System.setProperty("jna.library.path", ".");
        MyLib lib = (MyLib) Native.loadLibrary("mylib.so", MyLib.class);
        MyLib lib_copy = (MyLib) Native.loadLibrary("mylib_copy.so", MyLib.class);

        # set a common variable in mylib
        lib.set_(new IntByReference(9));

        # access the variable in mylib_copy
        IntByReference result = new IntByReference();
        lib_copy.get_(result);
        System.out.println(result.getValue());

    }

The output of the above code is 9, whichs means the two libraries seem to share their memory.

Is there a way to make them completely independent? I tried the same using Intel Fortran compiler, same result.

like image 624
Raphael Roth Avatar asked Oct 30 '22 23:10

Raphael Roth


1 Answers

JNA uses RTLD_LAZY|RTLD_GLOBAL when opening a library via dlopen, which is probably why the symbols are being shared. You can override those flags like so:

int RTLD_LOCAL = ??; // look this up on your system
Map options = new HashMap();
options.put(Library.OPTION_OPEN_FLAGS, RTLD_LOCAL);
MyLib mylib = Native.loadLibrary("mylib", MyLib.class, options);
MyLib mylib2 = Native.loadLibrary("mylib2", MyLib.class, options);
like image 102
technomage Avatar answered Nov 09 '22 13:11

technomage