子线程不能更新父线程变量?
Child thread can't update parent thread variable?
我在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
只有在 at the end of the start()
method, self.smtpd
is still None.
时才会产生上面的 RuntimeError
预期流量
start()
-> _run()
-> loop.create_server()
然后在第一次连接时:
loop.create_server()
-> _factory_invoker()
-> factory()
属性 smtpd
设置在 _factory_invoker
内 these lines:
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_exception
解释为 these 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.smtpd
是 None
,那么它只会在 _factory_invoker()
中出现错误时发生。如果是这样,错误应该已经被捕获并记录在 self._thread_exception
中。如果 self._thread_exception
是 None
,那么 _factory_invoker()
就成功了,因此 self.smtpd
不可能是 None
.
我解决此问题的主要问题是,在 所有 我的测试系统(Windows、Ubuntu、OpenSUSE、MacOS 和 FreeBSD)上,我从未遇到过类似的错误。
所以我很难过。对于解决此问题的任何想法,我将不胜感激。
好吧,显然我是被派去徒劳的。
复合因素是因为我在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
块修改为仅吞socket.socket_timeout
,实际问题浮出水面,我们可以快速解决。
都记录在aiosmtpd/244中,因此我不会在这里重复它们:-)
感谢所有花时间和精力尝试解决这个难题的人!
我在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
只有在 at the end of the start()
method, self.smtpd
is still None.
预期流量
start()
-> _run()
-> loop.create_server()
然后在第一次连接时:
loop.create_server()
-> _factory_invoker()
-> factory()
属性 smtpd
设置在 _factory_invoker
内 these lines:
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_exception
解释为 these 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.smtpd
是 None
,那么它只会在 _factory_invoker()
中出现错误时发生。如果是这样,错误应该已经被捕获并记录在 self._thread_exception
中。如果 self._thread_exception
是 None
,那么 _factory_invoker()
就成功了,因此 self.smtpd
不可能是 None
.
我解决此问题的主要问题是,在 所有 我的测试系统(Windows、Ubuntu、OpenSUSE、MacOS 和 FreeBSD)上,我从未遇到过类似的错误。
所以我很难过。对于解决此问题的任何想法,我将不胜感激。
好吧,显然我是被派去徒劳的。
复合因素是因为我在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
块修改为仅吞socket.socket_timeout
,实际问题浮出水面,我们可以快速解决。
都记录在aiosmtpd/244中,因此我不会在这里重复它们:-)
感谢所有花时间和精力尝试解决这个难题的人!