Private Package dll gives "Access is denied"

I am developing a private package which uses a dll I store in a “lib” folder in my package repository. This dll is from compiled c code and does not require registering and works fine from the development directory. The dll is loaded using Libdl.dlopen(). When I attempt to use my package from my private registry ( i.e. Pkg.add(“Package”) vs Pkg.develop(path=“path to Package”) ) I get an “Access is denied” error when dlopen() tries to load the dll. My suspicion is that this has something to do with Windows permissions, but I can’t figure out what is blocking the dll. I can easily navigate to the package folder in my “c:<UserName>.julia\packages” folder and delete the dll and replace it manually. When I do this I can successfully load the dll. But I don’t see any file properties or messages that indicate the dll is blocked or accessed by something else.

Any ideas of what is happening here?

I’m using v1.6.0 and Windows 10.

Things I’ve tried:

  1. Cloning my package repo manually and testing works fine
  2. Cloning my package repo manually into the c:<user name>.julia\packages folder testing works fine
  3. Deleting the dll and copy paste from my development folder works
  4. Pkg.add(“Package”) using Julia in Administrator mode does not make any difference, dll fails to load

So there is something about the way that Julia clones the repo that somehow blocks the dll.

Some more info and a workaround:

Here is what I see after the package is added from the registry…

julia> dll = raw"C:\Users\CarmanBr\.julia\packages\AM2App\IfOd6\lib\catapult_vs_F0_lib.dll"

julia> dlopen(dll)
ERROR: could not load library "C:\Users\CarmanBr\.julia\packages\AM2App\IfOd6\lib\catapult_vs_F0_lib.dll"
Access is denied.
 [1] dlopen(s::String, flags::UInt32; throw_error::Bool)
   @ Base.Libc.Libdl .\libdl.jl:114
 [2] dlopen
   @ .\libdl.jl:114 [inlined]
 [3] top-level scope
   @ REPL[9]:1

The workaround that I’ve figured out is I can copy and paste the file. After I do this the dll loads fine…

julia> cp(dll, dll*".copy", force=true)

julia> cp(dll*".copy",dll, force=true)

julia> hndl = dlopen(dll)
Ptr{Nothing} @0x00007ffc07780000

Make sure the library is executable, I think this should do the trick:

lib = "/path/to/library.dll"
chmod(lib, filemode(lib) | 0o755)

Thanks, this does the trick! What does 0o755 mean by the way? Where did you find this information? The help for filemode() and chmod() don’t explain much.

It’s the octal representation of the permissions:

  • read (4) + write (2) + execution (1) for the owning user
  • read (4) + execution (1) for the group owning user
  • read (4) + execution (1) for any other user

This is pretty standard in Unix systems, see for example Unix File Permissions - NERSC Documentation or the permissions calculator.

filemode(lib) | 0o755

basically means: to the current file permissions, add the necessary permissions to make the file readable and executable for any users, and writable by the owning user.

My brain :slightly_smiling_face: I bumped into the same issue some time ago: Dlopening MKL on Windows gives "Access is denied" error · Issue #38993 · JuliaLang/julia · GitHub. Julia v1.6 is stricter (and more correct) in this regard than previous versions, and expects libraries that you want to call into to be executable.

1 Like