Repository navigation
Regression: ImportError for HeaderWriteError in long-running process post-Python update for CVE-2024-6923 #124170
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Sep 17, 2024 I think the real fix is to not lazily import modules like this in the standard library, but I assume there's a reason email.generators is lazily imported?
Since yesterday I have the same error on my servers, using Python 3.8. It happens to crash my unicorn workers resulting in bad gateway errors for end users. Until I manually restart my servers. Happened yesterday and also today in the morning.
It happened to one of our servers as well. Running:
- Django 4.2.16
- gunicorn: 22.0.0
- Python 3.8.10
We upgraded recently to Django 4.2.16, commit django/django@bf4888d might be related.
Error
gunicorn[1014232]: [18/Sep/2024 10:58:11][common.services.pandora_service._user_access_token:187][Root=1-66ea9623-5aee4eae0266bcd41a3a1159][DEBUG] Token retrieved in : 9.248 ms gunicorn[1182738]: [2024-09-18 08:58:11 +0000] [1182738] [ERROR] Exception in worker process gunicorn[1182738]: Traceback (most recent call last): gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/arbiter.py", line 609, in spawn_worker gunicorn[1182738]: worker.init_process() gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/workers/ggevent.py", line 147, in init_process gunicorn[1182738]: super().init_process() gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 134, in init_process gunicorn[1182738]: self.load_wsgi() gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi gunicorn[1182738]: self.wsgi = self.app.wsgi() gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi gunicorn[1182738]: self.callable = self.load() gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 58, in load gunicorn[1182738]: return self.load_wsgiapp() gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp gunicorn[1182738]: return util.import_app(self.app_uri) gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/gunicorn/util.py", line 371, in import_app gunicorn[1182738]: mod = importlib.import_module(module) gunicorn[1182738]: File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module gunicorn[1182738]: return _bootstrap._gcd_import(name[level:], package, level) gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 1014, in _gcd_import gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 991, in _find_and_load gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 961, in _find_and_load_unlocked gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 1014, in _gcd_import gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 991, in _find_and_load gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 671, in _load_unlocked gunicorn[1182738]: File "<frozen importlib._bootstrap_external>", line 848, in exec_module gunicorn[1182738]: File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed gunicorn[1182738]: File "/opt/cloud/current/pix4uav/pix4d/__init__.py", line 3, in <module> gunicorn[1182738]: from .celery import app as celery_app # noqa gunicorn[1182738]: File "/opt/cloud/current/pix4uav/pix4d/celery.py", line 16, in <module> gunicorn[1182738]: from .settings.sentry import before_send gunicorn[1182738]: File "/opt/cloud/current/pix4uav/pix4d/settings/sentry.py", line 5, in <module> gunicorn[1182738]: from sentry_sdk.integrations.django import DjangoIntegration gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/sentry_sdk/integrations/django/__init__.py", line 61, in <module> gunicorn[1182738]: from sentry_sdk.integrations.django.middleware import patch_django_middlewares gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 38, in <module> gunicorn[1182738]: from .asgi import _asgi_middleware_mixin_factory gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/sentry_sdk/integrations/django/asgi.py", line 13, in <module> gunicorn[1182738]: from django.core.handlers.wsgi import WSGIRequest gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/django/core/handlers/wsgi.py", line 5, in <module> gunicorn[1182738]: from django.core.handlers import base gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 12, in <module> gunicorn[1182738]: from django.utils.log import log_response gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/django/utils/log.py", line 6, in <module> gunicorn[1182738]: from django.core import mail gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/django/core/mail/__init__.py", line 10, in <module> gunicorn[1182738]: from django.core.mail.message import ( gunicorn[1182738]: File "/opt/cloud/releases/20240913T095509/.venv/lib/python3.8/site-packages/django/core/mail/message.py", line 4, in <module> gunicorn[1182738]: from email import generator, message_from_string gunicorn[1182738]: File "/usr/lib/python3.8/email/generator.py", line 17, in <module> gunicorn[1182738]: from email.errors import HeaderWriteError gunicorn[1182738]: ImportError: cannot import name 'HeaderWriteError' from 'email.errors' (/usr/lib/python3.8/email/errors.py) gunicorn[1182738]: [2024-09-18 08:58:11 +0000] [1182738] [INFO] Worker exiting (pid: 1182738) gunicorn[1014225]: [2024-09-18 08:58:11 +0000] [1014225] [ERROR] Worker (pid:1182738) exited with code 3 gunicorn[1014228]: [2024-09-18 10:58:12 +0200] [1014228] [INFO] Worker exiting (pid: 1014228) gunicorn[1014235]: [2024-09-18 10:58:12 +0200] [1014235] [INFO] Worker exiting (pid: 1014235) gunicorn[1014232]: [2024-09-18 10:58:12 +0200] [1014232] [INFO] Worker exiting (pid: 1014232) gunicorn[1014229]: [2024-09-18 10:58:12 +0200] [1014229] [INFO] Worker exiting (pid: 1014229) gunicorn[1014225]: [2024-09-18 08:58:17 +0000] [1014225] [ERROR] Shutting down: Master gunicorn[1014225]: [2024-09-18 08:58:17 +0000] [1014225] [ERROR] Reason: Worker failed to boot. systemd[1]: gunicorn.service: Main process exited, code=exited, status=3/NOTIMPLEMENTED systemd[1]: gunicorn.service: Failed with result 'exit-code'.
We run on Django 3.2.9 (..i know), got the following error log. Still no solution found for the problem.
[2024-09-18 03:41:11 +0200] [17792] [INFO] Booting worker with pid: 17792 [2024-09-18 04:31:45 +0200] [18105] [INFO] Booting worker with pid: 18105 [2024-09-18 06:27:00 +0200] [20686] [INFO] Booting worker with pid: 20686 [2024-09-18 06:27:01 +0200] [20686] [ERROR] Exception in worker process Traceback (most recent call last): File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker worker.init_process() File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 119, in init_process self.load_wsgi() File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi self.wsgi = self.app.wsgi() File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 49, in load return self.load_wsgiapp() File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp return util.import_app(self.app_uri) File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/gunicorn/util.py", line 358, in import_app mod = importlib.import_module(module) File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1014, in _gcd_import File "<frozen importlib._bootstrap>", line 991, in _find_and_load File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 671, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 848, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/var/www/crftwrkbn/crftr/crftr/wsgi.py", line 13, in <module> from django.core.wsgi import get_wsgi_application File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/django/core/wsgi.py", line 2, in <module> from django.core.handlers.wsgi import WSGIHandler File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/django/core/handlers/wsgi.py", line 5, in <module> from django.core.handlers import base File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 12, in <module> from django.utils.log import log_response File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/django/utils/log.py", line 6, in <module> from django.core import mail File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/django/core/mail/__init__.py", line 9, in <module> from django.core.mail.message import ( File "/var/www/crftwrkbn/.venv/lib/python3.8/site-packages/django/core/mail/message.py", line 2, in <module> from email import ( File "/usr/lib/python3.8/email/generator.py", line 17, in <module> from email.errors import HeaderWriteError ImportError: cannot import name 'HeaderWriteError' from 'email.errors' (/usr/lib/python3.8/email/errors.py) [2024-09-18 06:27:01 +0200] [20686] [INFO] Worker exiting (pid: 20686) [2024-09-18 06:27:04 +0200] [542] [INFO] Shutting down: Master [2024-09-18 06:27:04 +0200] [542] [INFO] Reason: Worker failed to boot.It sounds like those of you who were getting this error were upgrading Python on the file system without restarting your processes. If so, you should be able to get around the issue by restarting all Python processes to have the new code.
Reacted by pm-atThanks for your reply. Hmm this could mean that the server restart solved the problem. In our setup with 4 web servers it could hypothetically be that yesterday server-1 and server-2 were automatically updated, and server-3 and server-4 today so that it should not happen anymore after today. Let's wait until tomorrow morning to see if this assumption is correct.
The question is, is a manual restart needed because unattended-upgrades did not do some restart and this error state will persist until the restart is done?
What are the possible options for current servers? So far I understand:
- restart python (what is the cleanest way to do that so that current python3 processes like
/usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggersand/usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signalare correctly started again?) - do a full system restart
- wait for the patch
Does the error happen again on systewms which are still running but everything was upgraded by
unattended-upgrades?- restart python (what is the cleanest way to do that so that current python3 processes like
how can one disable this automatic update ?
- added 8 commits that reference this issue
on Nov 10, 2024
Bug report
Bug description:
Pull request #122233 introduced a new class
HeaderWriteErrorin commit 0976339 and imports that fromemail.generator.This breaks running applications that have imported other parts of
emailbefore the update, and then try to import the generator past the update.Now this is a bit silly, but it is what
email.message.Message.as_string()does, it importsemail.generatorinside the function - which may happen at any point of the program run-time rather than at startup.For example, the following pseudo-code will fail, assuming it has not generated another email earlier or manually imported the
email.generatormodule.A particular instance of the issue is the
unattended-upgradespackage in Ubuntu and Debian, which will install the security update and then may send an email and fail there due to the ImportError, see https://bugs.launchpad.net/ubuntu/+source/python3.8/+bug/2080940.I'm wondering if it's feasible to add a workaround to the stable branches:
Cchange the email.generator module import:
to graciously support the previous version email.errors:
This is a safe change, existing applications, where the import fails can't be having
except HeaderWriteErrorstatements anyway.Thanks.
CPython versions tested on:
3.12
Operating systems tested on:
No response