python-daemon阻止ioctl调用ctypes链接C userlib

时间:2012-06-28 22:18:18

标签: python ctypes bottle ioctl python-daemon

我在瓶子web服务器中有一个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中的print语句显示我的设备节点的文件描述符已正确打开,但ioctl函数静默失败,错误代码为-1。

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

连连呢?目前,我已经准备好放弃守护进程模块了,因为一切都运行正常。

谢谢!

1 个答案:

答案 0 :(得分:1)

在准备这个问题时,答案对我来说很明显。

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

python-daemon在进入上下文时关闭所有文件句柄 - 包括硬件设备的继承文件描述符。 userlib仍然认为文件描述符是有效的。至少,它会将我的调试消息中的FD打印为整数>但是,在userlib不知道的情况下,文件句柄确实已经关闭,因此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。 ...我发现在守护进程中打开文件描述符更容易。 :)

希望这有助于其他人。 :)