Opened 8 months ago

Last modified 2 months ago

#9386 new bug

GHCi cannot load .so in ./

Reported by: crockeea Owned by:
Priority: normal Milestone:
Component: Compiler Version: 7.8.3
Keywords: Cc: hvr
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Other Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions: Phab:D593

Description (last modified by crockeea)

In my directory ./ I have an empty file Foo.hs and a shared object file mylib.so. From that directory in the shell,

$ ghci Foo *.so
GHCi, version 7.8.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading object (dynamic) mylib.so ... failed.
<command line>: user specified .o/.so/.DLL could not be loaded (mylib.so: cannot open shared object file: No such file or directory)
Whilst trying to load: (dynamic) mylib.so
Additional directories searched: (none)

It's interesting that GHCi searches ./ and identifies the correct object file, but then fails to load it. I have also tried the path ./*.so, mylib.so and ./mylib.so for the GHCi option.

However, if I move mylib.so to a directory ./Temp,

$ ghci Foo Temp/*.so

loads without issue.

Change History (12)

comment:1 Changed 8 months ago by crockeea

  • Summary changed from GHCi cannot load .so in same ./ to GHCi cannot load .so in ./

comment:2 Changed 8 months ago by crockeea

  • Description modified (diff)

comment:3 Changed 5 months ago by thomie

  • Status changed from new to infoneeded

crockeea: I am not able to reproduce your issue on Ubuntu x86_64.

$ cp /usr/lib/x86_64-linux-gnu/libbsd.so -H .

$ touch Foo.hs

$ ghc-7.8.2 --interactive Foo *.so
GHCi, version 7.8.2: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading object (dynamic) libbsd.so ... done
final link ... done
[1 of 1] Compiling Main             ( Foo.hs, interpreted )
Ok, modules loaded: Main.

Which OS and architecture are you using? Could you supply the most simple source for mylib.so with which you encounter this issue, including build and run instructions. Thanks!

comment:4 Changed 5 months ago by crockeea

  • Cc hvr added
  • Component changed from Compiler to GHCi
  • Status changed from infoneeded to new
  • Type of failure changed from GHCi crash to Other
  • Version changed from 7.8.2 to 7.8.3

I'm still experiencing this issue with ghc-7.8.3-x86-64-unknown-linux and gcc-4.8.2.

Consider the following C file, mul.c:

//zipWith (*)
void mul (int* a, int* b, int n) {
  int i;
  for(i = 0; i < n; i++) {
    a[i] = a[i]*b[i];
  }
}

At the terminal (where Foo.hs is empty):

> gcc -c mul.c
> gcc -shared -o mylib.so *.o
> ghci Foo *.o
GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading object (dynamic) mylib.so ... failed.
<command line>: user specified .o/.so/.DLL could not be loaded (mylib.so: cannot open shared object file: No such file or directory)
Whilst trying to load:  (dynamic) mylib.so
Additional directories searched: (none)
> mkdir Temp
> cp *.so Temp/
> ghci Foo Temp/*.o
GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading object (static) Temp/*.o ... not found
final link ... done
[1 of 1] Compiling Main             ( Foo.hs, interpreted )
Ok, modules loaded: Main.
*Main>

comment:5 follow-up: Changed 3 months ago by rwbarton

hvr: presumably dlopen is finding the libbsd.so on your library path, not the one in ..

I can reproduce this in 7.8.3 but not in HEAD, so I guess it is fixed, though I don't know why yet.

comment:6 Changed 3 months ago by rwbarton

Actually it's not fixed, it just works for the inplace GHC only, because the inplace/bin/ghc-stage2 sets LD_LIBRARY_PATH=...:$LD_LIBRARY_PATH, my existing LD_LIBRARY_PATH is empty and so GHC's LD_LIBRARY_PATH gets an empty component at the end, which is interpreted as the current directory...

It's actually not entirely clear what the behavior of ghci Foo libbar.so should be; maybe it should search the system library path for libbar.so, like it does today? But I'm inclined to say not, since you could get that behavior with ghci Foo -lbar instead.

The fact that it doesn't work even when you specify ./mylib.so is clearly wrong. I guess the pathname gets normalized before being passed to dlopen, but I don't yet know where or why.

I'm inclined to fix it with a hammer by prepending ./ to the dlopen argument whenever it is a relative pathname (if its argument contains a / then dlopen will treat it is as a pathname and not search the system library path).

comment:7 Changed 3 months ago by crockeea

  • Component changed from GHCi to Compiler

For the purposes of finding and fixing the bug, here are two more tidbits:

  1. This bug also affects GHC with .so files
  2. This bug does not affect .o files. In that case, I can just type a list of files a.o b.o ... and GHC searches the local directory. This seems to support your suggested solution to just prepend a ./ to paths. But why is the behavior different for .o and .so files? Perhaps it's a matter of hardcoded extensions?

comment:8 in reply to: ↑ 5 Changed 3 months ago by thomie

Replying to rwbarton:

presumably dlopen is finding the libbsd.so on your library path, not the one in ..

Correct. When I remove /usr/lib/x86_64-linux-gnu/libbsd.so, the test from comment:3 also fails.

comment:9 Changed 3 months ago by rwbarton

As a workaround, you can use an absolute path ghci Foo `pwd`/*.so.

comment:10 Changed 3 months ago by thoughtpolice

  • Differential Revisions set to Phab:D593

comment:11 Changed 3 months ago by Reid Barton <rwbarton@…>

In fe0d289de466b0c34a04350c6f7c096d9a588ad0/ghc:

inplace: Don't add empty component to LD_LIBRARY_PATH when it is empty

Summary: Avoids a confusing inconsistency when testing #9386 (about ghci finding .so files in .).

Test Plan: validate

Reviewers: austin

Reviewed By: austin

Subscribers: carter, thomie

Differential Revision: https://phabricator.haskell.org/D593

GHC Trac Issues: #9386

comment:12 Changed 2 months ago by rwbarton

I did some experiments with gcc ... libfoo.so, and it looked for libfoo.so in the current directory only, so I guess ghc and ghci ought to do the same.

Note: See TracTickets for help on using tickets.