脳汁でコードを書く

Archive for 3 月 7th, 2010

snow leopard(x86-64)のsbclで普通のdlopenを利用する

日曜日, 3 月 7th, 2010

snow leopard上のsbclは大体うまく動くのですが, FFIでCの関数を呼びだしはじめると, 結構うまくいかないことがあります.

snow leopard上でsbclを使ってるひとは

(load-shared-object "/usr/X11R6/lib/libX11.dylib")
(load-shared-object "/usr/X11R6/lib/libGL.dylib")

とすると, プロセスが帰ってこなくなることが確認できます.

これは, darwinにおいて, sbclは普通のdlopenを利用してないことが原因だと思われます.

これはdarwinは標準的なELFではなく, バイナリがMach-o形式のため, dlopenを<mach-o/dyld.h>を利用してエミュレートしているのが原因だと思われます(sbcl/src/runtime/darwin-dlshim.c).

しかし, よく考えると, mac os xのgccは普通にdlopenを提供してくれているので, そっちを使うほうが良いです.

その辺のことがPHPまわりで議論されてるようです. ruby 1.8.6だloadできないけど, 1.8.7だとできるみたいな話もあるらしいです (url紛失).

以下あやしいところもありますが, このためのパッチになります.

利用してるのはcvsの最新のものです(1.0.36.13).

Index: sb-bsd-sockets/defpackage.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/contrib/sb-bsd-sockets/defpackage.lisp,v
retrieving revision 1.14
diff -r1.14 defpackage.lisp
76a77,79
>
> #+darwin
> (load-shared-object "/usr/lib/libc.dylib")
Index: contrib/sb-posix/defpackage.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/contrib/sb-posix/defpackage.lisp,v
retrieving revision 1.16
diff -r1.16 defpackage.lisp
26a27,29
>
> #+darwin
> (sb-alien:load-shared-object "/usr/lib/libc.dylib")
Index: src/code/unix-foreign-load.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/code/unix-foreign-load.lisp,v
retrieving revision 1.1
diff -r1.1 unix-foreign-load.lisp
34a35
>
69c70,71
<   (let* ((extern (extern-alien-name symbol))
---
>   (let* ((extern #!-mach-o (extern-alien-name symbol)
>                  #!+mach-o (coerce symbol 'base-string))
Index: src/runtime/Config.x86-64-darwin
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/Config.x86-64-darwin,v
retrieving revision 1.4
diff -r1.4 Config.x86-64-darwin
13,14c13,15
< LINKFLAGS += -mmacosx-version-min=10.4
< OS_SRC = bsd-os.c x86-64-bsd-os.c darwin-os.c x86-64-darwin-os.c darwin-dlshim.c darwin-langinfo.c
---
> LINKFLAGS += -mmacosx-version-min=10.4 -ldl
> #OS_SRC = bsd-os.c x86-64-bsd-os.c darwin-os.c x86-64-darwin-os.c darwin-dlshim.c darwin-langinfo.c
> OS_SRC = bsd-os.c x86-64-bsd-os.c darwin-os.c  darwin-langinfo.c
Index: src/runtime/Config.x86-64-darwin9+
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/Config.x86-64-darwin9+,v
retrieving revision 1.1
diff -r1.1 Config.x86-64-darwin9+
14c14,15
< OS_SRC = bsd-os.c x86-64-bsd-os.c darwin-os.c x86-64-darwin-os.c darwin-dlshim.c darwin-langinfo.c
---
> #OS_SRC = bsd-os.c x86-64-bsd-os.c darwin-os.c x86-64-darwin-os.c darwin-dlshim.c darwin-langinfo.c
> OS_SRC = bsd-os.c x86-64-bsd-os.c darwin-os.c x86-64-darwin-os.c darwin-langinfo.c
Index: src/runtime/x86-64-darwin-os.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-64-darwin-os.c,v
retrieving revision 1.14
diff -r1.14 x86-64-darwin-os.c
25a26,29
> // added by garaemon
> #include <dlfcn.h>
> #include <sys/wait.h>
> #include <mach-o/dyld.h>
688a693,697
> //dummy function
> /* void darwin_waitpid(int pid, int* status, int options) { */
> /*     waitpid(pid, status, options); */
> /* } */
>
Index: tools-for-build/ldso-stubs.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/tools-for-build/ldso-stubs.lisp,v
retrieving revision 1.24
diff -r1.24 ldso-stubs.lisp
327,331c327,337
<                  #!-darwin
<                  '("dlclose"
<                    "dlerror"
<                    "dlopen"
<                    "dlsym")
---
>                  ;; #!-darwin
>                   '("dlclose"
>                     "dlerror"
>                     "dlopen"
>                     "dlsym")
>                   #!+darwin
>                   '("waitpid"
>                     "ptsname"
>                     "grantpt"
>                     "unlockpt")
>                   ;; for bsd-sockets...?

sb-posixとsb-bsd-socketsでlibc.dylibをloadしなくてはいけなくなったのは理由がよくわかりません… -lcはつけてるはずですが

追記:

バグレポートしておいた

https://bugs.launchpad.net/sbcl/+bug/533470

追記2:

slimeでthreadを利用してる場合は, load-shared-objectでハングする可能性があります. dlopenはmmapとかしてそうだからそのへんかな?

以下解決のためのpatch

Index: swank-sbcl.lisp
===================================================================
RCS file: /project/slime/cvsroot/slime/swank-sbcl.lisp,v
retrieving revision 1.269
diff -r1.269 swank-sbcl.lisp
71c71
<     ((member :sb-thread *features*) :spawn)
---
>     ;;((member :sb-thread *features*) :spawn)
1345c1345
< #+(and sb-thread
---
> #+(and nil sb-thread