golang os.Setenv does not work in cgo C.dlopen?

huangapple go评论83阅读模式
英文:

golang os.Setenv does not work in cgo C.dlopen?

问题

由于某种原因,我无法将$LD_LIBRARY_PATH设置为全局环境变量。我尝试在golang代码中使用os.Setenv来设置它。

os.Setenv("LD_LIBRARY_PATH", my_library_paths)

lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)

我使用另一个C++函数来获取$LD_LIBRARY_PATH,它显示正确。

但是lib返回<nil>,而C.dlerror()显示:

libhasp_linux_x86_64_demo.so: cannot open shared object file: No such file or directory

这意味着$LD_LIBRARY_PATH在dlopen中不起作用,cgo找不到依赖库。

我不知道为什么。希望有人能帮助我。谢谢!

英文:

For some reason, I can not set $LD_LIBRARY_PATH to global env. I try to set it up in golang code use os.Setenv.

os.Setenv(&quot;LD_LIBRARY_PATH&quot;, my_library_paths)

lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)

I use another C++ function to get $LD_LIBRARY_PATH, it shows corretly.
But lib returns '&lt;nil&gt;', and C.dlerror() shows

&gt;&gt; %!(EXTRA string=libhasp_linux_x86_64_demo.so: cannot open shared object file: No such file or directory)

Means $LD_LIBRARY_PATH does not work in dlopen, cgo can not find depend libraries.

I don't know why.Hope some one can help me.Thanks!

答案1

得分: 2

看起来你正在尝试从“同一进程内”调用os.Setenv("LD_LIBRARY_PATH", ...)C.dlopen()

根据dlopen(3)的手册:

否则,动态链接器按以下方式搜索对象

...

如果在程序启动时,环境变量LD_LIBRARY_PATH被定义为包含以冒号分隔的目录列表,则会搜索这些目录。

关键词是“在程序启动时”。我们可以在glibc源码elf/dl-load.c中的dlopen实现中看到,它查看一个全局变量__rtld_env_path_list.dirs,该变量在搜索要加载的库时已经被设置好了;它不会查看当前的$LD_LIBRARY_PATH的值。

如果你想在C.dlopen中使用LD_LIBRARY_PATH来查找内容,那么你需要在进程启动之前设置它(例如通过运行LD_LIBRARY_PATH=/my/path go run my-app.go)。

英文:

It looks like you're trying to call os.Setenv(&quot;LD_LIBRARY_PATH&quot;, ...) and then C.dlopen() from within the same process.

From the man page dlopen(3):

> Otherwise, the dynamic linker searches for the object as follows
>
> ...
>
> If, at the time that the program was started, the environment variable LD_LIBRARY_PATH was defined to contain a colon-separated list of directories, then these are searched.

The key phrase being, at the time the program is started. We can see in the implementation for dlopen in the glibc source elf/dl-load.c that it looks at a global variable __rtld_env_path_list.dirs that has already been set when searching for libraries to load; it does not look at the current value of $LD_LIBRARY_PATH.

If you want to use LD_LIBRARY_PATH to find things in C.dlopen, then you'll need to set it before your process starts (by running e.g. LD_LIBRARY_PATH=/my/path go run my-app.go).

答案2

得分: 0

正如KJ Tsanaktsidis正确回答的那样,LD_LIBRARY_PATH在进程启动后没有效果;您必须在启动进程之前设置它。

一种常见的技术是检查LD_LIBRARY_PATH的当前值,如果不符合您的要求,将其设置为新值,并重新exec进程。

话虽如此,不清楚您为什么要首先设置LD_LIBRARY_PATH。如果您使用绝对路径调用dlopen,它将愉快地打开不在LD_LIBRARY_PATH上的库。也就是说,不要这样做:

> os.Setenv(&quot;LD_LIBRARY_PATH&quot;, my_library_paths)<br>
> lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)

而是这样做:

  lib := C.dlopen(C.CString(absolute_path_to_library), C.RTLD_LAZY)
英文:

As KJ Tsanaktsidis correctly answered, LD_LIBRARY_PATH has no effect after the process has started; you must set it before starting the process.

A common technique is to examine current value of LD_LIBRARY_PATH, and if it's not to your liking, set it to new value and re-exec the process.

That said, it's not clear why you want set LD_LIBRARY_PATH in the first place. dlopen will happily open a library which is not on LD_LIBRARY_PATH if you invoke dlopen with absolute path. That is, instead of doing this:

> os.Setenv(&quot;LD_LIBRARY_PATH&quot;, my_library_paths)<br>
> lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)

do this:

  lib := C.dlopen(C.CString(absolute_path_to_library), C.RTLD_LAZY)

huangapple
  • 本文由 发表于 2021年9月7日 18:17:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/69086379.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定