子线程不能更新父线程变量?

时间:2021-02-16 09:30:10

标签: python python-asyncio python-multithreading aiosmtpd

我在 aiosmtpd/244 中发现了一个非常令人困惑的问题,在这里分享我的困惑,以帮助我找到解决问题的灵感。

情况

  • 两台运行 Red Hat 7.9 的服务器
  • Works on one,不适用于另一个
  • 有问题的代码,简化了:
>>> from aiosmtpd.controller import Controller
>>> from aiosmtpd.handlers import Sink
>>> cont = Controller(Sink())
>>> cont.start()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/aiosmtpd/controller.py", line 180, in start
    raise RuntimeError("Unknown Error, failed to init SMTP server")
RuntimeError: Unknown Error, failed to init SMTP server

上述 RuntimeError 只能在 at the end of the start() method, self.smtpd is still None 时产生。

预期流量

start() -> _run() -> loop.create_server()

然后在第一次连接时:

loop.create_server() -> _factory_invoker() -> factory()

属性 smtpd 设置在 these lines 中的 _factory_invoker 中:

        try:
            self.smtpd = self.factory()
            if self.smtpd is None:
                raise RuntimeError("factory() returned None")
            return self.smtpd
        except Exception as err:
            self._thread_exception = err
            return _FakeServer(self.loop)

self._thread_exceptionthese lines 中解释:

        if self._thread_exception is not None:
            raise self._thread_exception
        # Defensive
        if self.smtpd is None:
            raise RuntimeError("Unknown Error, failed to init SMTP server")

如您所见,如果 self.smtpdNone,那么只有在 _factory_invoker() 中存在错误时才会发生这种情况。如果是这样,错误应该已经被捕获并记录在 self._thread_exception 中。如果 self._thread_exceptionNone,那么 _factory_invoker() 已经成功,因此 self.smtpd 不可能是 None

我在解决这个问题时遇到的主要问题是,在我的所有测试系统(Windows、Ubuntu、OpenSUSE、MacOS 和 FreeBSD)上,我从未遇到过类似的错误。

所以我很难过。如果您有任何解决此问题的想法,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

好吧,很明显我被派去大奔了。

复合因素是因​​为我抑制了these lines中的所有异常

        try:
            self._testconn()
        except Exception:
            # We totally don't care of exceptions experienced by _testconn,
            # which _will_ happen if factory() experienced problems.
            pass

因此,在 self._testconn() 中引发的一个非常 非常有用的异常被吞没了。

显然 self._testconn() 尝试连接到 host:port 失败,因此 _factory_invoker() 从未 被调用。 >

一旦将 try..except 块修改为 only 吞下 socket.socket_timeout,实际问题浮出水面,我们可以快速修复它。

这一切都记录在 aiosmtpd/244 中,因此我不会在这里重复它们:-)

感谢所有花费时间和精力尝试解决这个难题的人!

相关问题