dl.open() ipython 的权限被拒绝,但 python 的权限未被拒绝

Permission denied on dl.open() with ipython but not with python

我最初的目标是使用 ctypes 在 Cygwin 上打开一个 dll 文件。但是我发现了一些问题。我只在 IPython.

上挖到了 sys.dl 其中 returns 一个未知的 Permission denied

python 一切正常:

$ ls
my.dll
$ python
Python 2.7.8 (default, Jul 28 2014, 01:34:03)
[GCC 4.8.3] on cygwin
>>> import dl
>>> dl.open('my.dll')
<dl.dl object at 0xfffaa0c0>

使用 ipython 我得到错误:

$ ipython
Python 2.7.8 (default, Jul 28 2014, 01:34:03)   
In [1]: import dl   
In [2]: dl.open('my.dll')
---------------------------------------------------------------------------
error Traceback (most recent call last)
<ipython-input-2-c681630fa713> in <module>()
----> 1 dl.open('my.dll')

error: Permission denied

我使用 strace 对此进行了调查。 `IPython 的输出日志很大,超过 4MB。幸运的是,我发现了一些奇怪的东西:

symlink.check(C:\Users\user\Home\projects\foo\my.dll, 0x28AB88) (0x4022)
   35 2705178 [main] python2.7 16924 path_conv::check: this->path(C:\Users\user\Home\projects\foo\my.dll), has_acls(1)
   37 2705215 [main] python2.7 16924 cwdstuff::get: posix /cygdrive/c/Users/user/Home/projects/foo
   32 2705247 [main] python2.7 16924 cwdstuff::get: (C:\Users\user\Home\projects\foo) = cwdstuff::get (0x8006ECF0, 32768, 0, 0), errno 11
--- Process 14376, exception c0000138 at 7726163E
 3286 2708533 [main] python2.7 16924 seterrno_from_win_error: /home/corinna/src/cygwin/cygwin-1.7.35/cygwin-1.7.35-1.i686/src/src/winsup/cygwin/dlfcn.cc:174 windows error 182
   42 2708575 [main] python2.7 16924 geterrno_from_win_error: unknown windows error 182, setting errno to 13
   36 2708611 [main] python2.7 16924 dlopen: ret 0x0

/home/corinna是谁?我的安装中没有 corinna 用户,我的 Windows 上也没有。 Corinna 并非来自我的装置。它是一些硬编码的东西吗?

现在,这是我从 strace 获得的 python:

symlink.check(C:\Users\user\Home\projects\foo\my.dll, 0x28B728) (0x4022)
   26 10440048 [main] python 12604 path_conv::check: this->path(C:\Users\user\Home\projects\foo\my.dll), has_acls(1)
   23 10440071 [main] python 12604 cwdstuff::get: posix /cygdrive/c/Users/user/Home/projects/foo
   25 10440096 [main] python 12604 cwdstuff::get: (C:\Users\user\Home\projects\foo) = cwdstuff::get (0x8006ECF0, 32768, 0, 0), errno 0
 3405 10443501 [main] python 12604 dlopen: ret 0x5B9C0000   

dlopen 在 IPython 中返回 0x0,而在 python 中返回 0x5B9C0000。我注意到 cwdstuff::get 在调用 dlopen 之前引发错误。

编辑 我向 Cygwin 的邮件列表发送了一条消息,关于此问题的 answer of Corinna 是:

This is not Cygwin's fault, AFAICS. Cygwin never loads functions by ordinal. This is also a bit on the lean side as far as information is concerned. One can't see how the process calls dlopen, for instance. Corinna How to solve this issue?

我之前的测试使用 ctypes

最初,当我问我的问题时,我只是在玩 ctypes。 我正在使用 Cygwin 32 位和 Windows 7。 使用 IPython,当我尝试使用 cdll.LoadLibrary 加载 dll 时,我得到了一个 OSError

两个想法:

1) 在下一个单元格中,键入 %pdb,然后交互 "print self._name" 以查看它是什么。

2) 使用 cdll.LoadLibrary("foo.dll") 的完整路径查看是否有效。

一旦你知道问题是什么,然后你就可以确定它是谁的错误,并报告它(可能是 ctypes 问题,但可能 ipython)

  • 也许 Python 可执行文件和 IPython 内核使用不同的清单文件来定义加载策略?

  • 在这两种情况下,
  • 尝试将 DLL 路径附加到 sys.path。

  • 在这两种情况下检查管理员权限 (UAC)。

  • 使用 dependency walker 找出这个 DLL 的依赖关系。也许问题来自依赖关系?

  • 可能你的机器有这个 DLL 的多个副本?

  • 最后,您可以使用 Process Explorer 查看两种情况下加载的 DLL 列表,并查看任何差异。

我正在处理一个非常相似的问题:

ipython notebook & script difference - loading DLLs

更多想法:

  • 检查访问DLL的用户是否相同。你这样做:

    import getpass

    print(getpass.getuser())

  • 检查当前进程实际在做什么。我没有使用过 cygwin,但是在 linux shell 中,可执行文件 strace 应该会告诉你这个。 用法:获取当前进程的 PID:import os; os.getpid() 在此之后,您可以使用(从 python/ipython 控制台外部使用命令 strace -p <the pid> -e file。完成此设置后,您可以尝试加载 DLL。

备注:-e file标志应该这样写。 file 这个词告诉 strace 报告进程进行的所有文件操作。如果 python/ipython 上的 运行 没有出现差异,您可以尝试删除 -e file 标志。然后您将看到该进程进行的所有系统调用。我没有像那样处理 windows,所以这可能根本不起作用,但至少在 linux 上,这应该向您报告该过程所做的一切。您至少可以在那里看到所有打开的文件,但也可以在那里找到更多有趣的东西。如果输出相同,则可以在python/ipython中进一步调试问题。这基本上需要@Doug Blank 建议的内容,但我还建议调查每个被触及的名称(变量)。 self_dlopenmode 名称听起来也可能包含有用的信息。

否则,执行 dir(self)dir(_dlopen) 以查看您可以在那里找到哪些其他属性可能已被 IPYthon 修改。

先尝试这些,然后我们可以帮助您进一步挖掘。