Pylons 中的信号处理

发布于 2024-10-31 21:31:27 字数 364 浏览 1 评论 0原文

我有一个塔项目,我需要定期更新一些内存中的结构。这应该按需完成。我决定为此想出一个信号处理程序。用户将 SIGUSR1 发送到主 pylons 线程,并由项目处理。

这有效,除非在处理信号后,服务器崩溃并出现以下异常:

File "/usr/lib/python2.6/SocketServer.py", line 264, in handle_request
   fd_sets = select.select([self], [], [], timeout)
select.error: (4, 'Interrupted system call')

是否可以解决此问题?

TIA。

I have a pylons project where I need to update some in-memory structures periodically. This should be done on-demand. I decided to come up with a signal handler for this. User sends SIGUSR1 to the main pylons thread and it is handled by the project.

This works except after handling the signal, the server crashes with following exception:

File "/usr/lib/python2.6/SocketServer.py", line 264, in handle_request
   fd_sets = select.select([self], [], [], timeout)
select.error: (4, 'Interrupted system call')

Is it possible to fix this?

TIA.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

揽月 2024-11-07 21:31:27

是的,这是可能的,但使用现有的 Python 库并不容易。这是由于 Python 将所有操作系统错误转换为异常。然而,EINTR 确实应该导致所使用的系统调用重试。每当您开始在 Python 中使用信号时,您都会偶尔看到此错误。

我有修复此问题的代码( SafeSocket),通过分叉 Python 模块并添加该功能。但在使用系统调用的地方都需要添加它。所以这是可能的,但并不容易。但你可以使用我的开源代码,它可能会节省你多年的工作。 ;-)

基本模式是这样的(作为系统调用装饰器实现):

# decorator to make system call methods safe from EINTR
def systemcall(meth):
    # have to import this way to avoid a circular import
    from _socket import error as SocketError
    def systemcallmeth(*args, **kwargs):
        while 1:
            try:
                    rv = meth(*args, **kwargs)
            except EnvironmentError as why:
                if why.args and why.args[0] == EINTR:
                    continue
                else:
                    raise
            except SocketError as why:
                if why.args and why.args[0] == EINTR:
                    continue
                else:
                    raise
            else:
                break
        return rv
    return systemcallmeth

您也可以在 select 调用周围使用它。

Yes, it is possible, but not easy using the stock Python libraries. This is due to Python translating all OS errors to exceptions. However, EINTR should really cause a retry of the system call used. Whenever you start using signals in Python you will see this error sporadically.

I have code that fixes this (SafeSocket), by forking Python modules and adding that functionality. But it needs to be added everywhere system calls are used. So it's possible, but not easy. But you can use my open-source code, it may save you years of work. ;-)

The basic pattern is this (implemented as a system call decorator):

# decorator to make system call methods safe from EINTR
def systemcall(meth):
    # have to import this way to avoid a circular import
    from _socket import error as SocketError
    def systemcallmeth(*args, **kwargs):
        while 1:
            try:
                    rv = meth(*args, **kwargs)
            except EnvironmentError as why:
                if why.args and why.args[0] == EINTR:
                    continue
                else:
                    raise
            except SocketError as why:
                if why.args and why.args[0] == EINTR:
                    continue
                else:
                    raise
            else:
                break
        return rv
    return systemcallmeth

You could also just use that around your select call.

风吹过旳痕迹 2024-11-07 21:31:27

一个修复,至少对我有用,来自 12 岁的 python -dev list post

    while True:
        try:
            readable, writable, exceptional = select.select(inputs, outputs, inputs, timeout)
        except select.error, v:
            if v[0] != errno.EINTR: raise
        else: break

实际选择行的详细信息并不重要...您的“fd_sets = select.select([self], [], [], timeout)”行应该完全相同。

重要的是检查 EINTR 并重试/循环(如果捕获)。
哦,别忘了导入 errno。

A fix, at least works for me, from an 12 year old python-dev list post

    while True:
        try:
            readable, writable, exceptional = select.select(inputs, outputs, inputs, timeout)
        except select.error, v:
            if v[0] != errno.EINTR: raise
        else: break

The details of the actual select line isn't important... your "fd_sets = select.select([self], [], [], timeout)" line should work exactly the same.

The important bit is to check for EINTR and retry/loop if that is caught.
Oh, and don't forget to import errno.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文