python-daemon 阻止对 ctypes 链接的 C 用户库的 ioctl 调用

Posted

技术标签:

【中文标题】python-daemon 阻止对 ctypes 链接的 C 用户库的 ioctl 调用【英文标题】:python-daemon blocks ioctl call to ctypes linked C userlib 【发布时间】:2012-06-28 22:18:18 【问题描述】:

我在瓶网络服务器中有一个 Python 应用程序,它通过 Linux 平台上的 ctypes Python 模块访问 C 共享对象库。 C so-lib 打开一个设备节点 (/dev/myhwdev) 并针对设备的文件描述符声明一个 IOCTL 函数。虽然这是一个复杂的堆栈,但在我将瓶子应用程序包装在 Python 的 python-daemon 上下文中之前它工作得很好,如下所示:

# -*- coding: utf-8 -*-
import daemon
import bottle
from bottle import run, route, request

from userlib_via_ctypes_module import *
userlib_grab_device_file_descriptor()

@route('/regread')
def show_regread():
    address = request.query.address or request.forms.address
    length = request.query.length or request.forms.length
    return 'results':assert_ioctl_via_userlib(address, length)

daemonContext = daemon.DaemonContext(
    detach_process = False
    )
with daemonContext:
    try:
        run(host = '0.0.0.0', port = '80', debug = True)
    except:
        print "(E) Bottle web-service was stopped.\n";

只需注释掉 with daemonContext 行(并更正缩进)即可使此代码正常工作(即,提供正确的 JSON 结果)。但是,在 daemonContext 中,我的 userlib 中的打印语句显示我的设备节点的文件描述符已正确打开,但 ioctl 函数静默失败,错误代码为 -1。

关闭设备的文件描述符并重新打开它(在 userlib 代码或上述路由处理程序中)允许命令正常工作 - 一次。但是,守护进程和瓶服务器锁定并忽略所有进一步的网络请求。

建议?目前,我准备放弃 daemon 模块,因为没有它一切正常。

谢谢!

【问题讨论】:

【参考方案1】:

在准备这个问题时,答案对我来说变得显而易见。

userlib_grab_device_file_descriptor() 函数称为 C 级 SO-lib 函数,该函数打开硬件设备节点的文件描述符,该文件描述符已传递给 userlib ioctl 函数。

python 守护进程在进入上下文时关闭所有文件句柄 - 包括硬件设备的继承文件描述符。 userlib 仍然认为文件描述符是有效的。至少,它会在我的调试消息中将 FD 打印为整数 > 2。但是,用户库不知道,文件句柄确实已关闭,因此 IOCTL 会默默地失败。我希望 uclib 或内核提供了更好的错误消息。 :(

无论如何,答案是将打开的文件句柄移动到守护进程上下文的内部,如下所示:

...
with daemonContext:
    try:
        userlib_grab_device_file_descriptor()   # open fd here
        run(host = '0.0.0.0', port = '80', debug = True)
    except:
        print "(E) Bottle web-service was stopped.\n";

我尝试使用 python-daemon 的 files_preserve 属性,但它适用于文件描述符编号,而不是文件名。因此,在打开 fd 之后,我的 userlib 必须将 fd 编号传递给守护进程,因此它可以在进入守护进程之前排除 fd。 ...我发现打开守护进程内部的文件描述符更容易。 :)

希望这对其他人有所帮助。 :)

【讨论】:

理性地思考问题总是好的,有时尝试提出正确的问题是这样做的最佳时机;) 同意如果 fd 已关闭或重新用于其他文件,您的 C 库应该返回 EBADFENOTTY 到您的 ioctl() 调用。值得调查 C 库源并与他们一起提交错误报告...

以上是关于python-daemon 阻止对 ctypes 链接的 C 用户库的 ioctl 调用的主要内容,如果未能解决你的问题,请参考以下文章

我可以阻止 C++ dll 在 Python Ctypes 中加载吗?

python-daemon 中的信号处理

python-daemon 和多处理库之间的区别

我是不是正确使用 ctypes 来对这个结构进行 python 化?

Python 外部函数调用库ctypes简介

使用 ctypes 返回值