[BUG] Dash._setup_server() 中的竞争条件:保护的标志在其所保护的工作之前就已被设置
作者: a-tram创建于 2026年9月3日更新于 2026年9月10日
标签bugP2size: 5
Dash._setup_server() 运行作为一个 before_request 钩子,并且意在每个进程执行一次。它在执行保护该标志的工作之前设置其保护标志:
def _setup_server(self): # dash.py:1702
if self._got_first_request["setup_server"]:
return # <-- thread B 在这里离开
self._got_first_request["setup_server"] = True # <-- 标志在执行工作之前设置
...
_validate.validate_layout(self.layout, self._layout_value()) # 1724
self._generate_scripts_html() # 1726, 填充 registered_paths
...
self.callback_map[k] = _callback.GLOBAL_CALLBACK_MAP.pop(k) # 1737, 填充 callback_map这是一个 TOCTOU。在任何 WSGI 服务器上,该服务器在单个进程中同时处理多个请求 - gunicorn -k gthread --threads N,waitress,werkzeug 使用 threaded=True,uWSGI 使用线程 - 一个第二个线程可以在第一个线程仍然处于 _setup_server 中时进入,找到已经设置的标志,立即返回,然后读取第一个线程尚未完成写入的状态。它只影响 进程启动后的第一次页面加载,并且刷新使其消失,这就是为什么很容易将其视为缓存或网络故障。下面的两个症状均由进一步链接的脚本可靠地重现。
内容来源: plotly/dash