PR #5423 (to address issue #2700) made a change which installs a SIGTERM handler within Task.__call__(), which effectively ignores SIGTERM. This is...er...wrong, and leads to the following problems:
- Tasks cannot be called inline within a thread (eg common configurations of
uwsgi, or even Django's runserver)
- The warm/cold shutdown distinction is erased
- The
REMAP_SIGTERM configuration value is ignored (used in eg Heroku deployments)
- Signal handling by non-worker calling processes is forcibly overridden
- Conflicts with Celery's own worker signal handling (see worker.py and platforms.py)
The PR in question was reverted in #5577, then un-reverted in #5586.
We've had to add a custom task class and override __call__() for production use to avoid this issue. Please re-revert #5423; if #2700 is still an issue inherent to Celery (as opposed to simply warm/cold shutdown differences), then a different fix should be considered.
Edit: after some deeper looks at the code, it seems as though this only applies for inline tasks under the base Task class, as __call__() is optimized away (see trace.py) for async/dispatched tasks if it hasn't been overridden. AFAICT it would still be a problem if using a custom task class which overrides __call__() and calls super(), however.
Checklist
Mandatory Debugging Information
Related Issues and Possible Duplicates
Related Issues
Possible Duplicates
Environment & Settings
Celery version:
celery report Output:
software -> celery:4.4.0rc3 (cliffs) kombu:4.6.4 py:3.7.4
billiard:3.6.1.0 redis:3.3.7
platform -> system:Linux arch:64bit
kernel version:4.9.184-linuxkit imp:CPython
loader -> celery.loaders.app.AppLoader
settings -> transport:redis results:redis://mps-redis:6379/0
Steps to Reproduce
Required Dependencies
- Minimal Python Version: N/A or Unknown
- Minimal Celery Version: 4.4.0rc2
- Minimal Kombu Version: N/A or Unknown
- Minimal Broker Version: N/A or Unknown
- Minimal Result Backend Version: N/A or Unknown
- Minimal OS and/or Kernel Version: N/A or Unknown
- Minimal Broker Client Version: N/A or Unknown
- Minimal Result Backend Client Version: N/A or Unknown
Minimally Reproducible Test Case
See https://github.com/celery/celery/blob/master/celery/app/task.py#L396
Expected Behavior
Should be able to call a task inline in a thread.
Actual Behavior
When calling task inline under Django runserver (which uses threads):
Traceback (most recent call last):
File "/app/pipelines/serializers.py", line 184, in create
remote_worker=validated_data['with_remote'],
File "/usr/local/lib/python3.7/site-packages/celery/local.py", line 191, in __call__
return self._get_current_object()(*a, **kw)
File "/usr/local/lib/python3.7/site-packages/celery/app/task.py", line 396, in __call__
signal.signal(signal.SIGTERM, handle_sigterm)
File "/usr/local/lib/python3.7/signal.py", line 47, in signal
handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread
PR #5423 (to address issue #2700) made a change which installs a
SIGTERMhandler withinTask.__call__(), which effectively ignoresSIGTERM. This is...er...wrong, and leads to the following problems:uwsgi, or even Django'srunserver)REMAP_SIGTERMconfiguration value is ignored (used in eg Heroku deployments)The PR in question was reverted in #5577, then un-reverted in #5586.
We've had to add a custom task class and override
__call__()for production use to avoid this issue. Please re-revert #5423; if #2700 is still an issue inherent to Celery (as opposed to simply warm/cold shutdown differences), then a different fix should be considered.Edit: after some deeper looks at the code, it seems as though this only applies for inline tasks under the base
Taskclass, as__call__()is optimized away (see trace.py) for async/dispatched tasks if it hasn't been overridden. AFAICT it would still be a problem if using a custom task class which overrides__call__()and callssuper(), however.Checklist
contribution guide
on reporting bugs.
for similar or identical bug reports.
for existing proposed fixes.
to find out if the bug was already fixed in the master branch.
in this issue (If there are none, check this box anyway).
Mandatory Debugging Information
celery -A proj reportin the issue.(if you are not able to do this, then at least specify the Celery
version affected).
masterbranch of Celery.pip freezein the issue.to reproduce this bug.
Related Issues and Possible Duplicates
Related Issues
Possible Duplicates
Environment & Settings
Celery version:
celery reportOutput:Steps to Reproduce
Required Dependencies
Minimally Reproducible Test Case
See https://github.com/celery/celery/blob/master/celery/app/task.py#L396
Expected Behavior
Should be able to call a task inline in a thread.
Actual Behavior
When calling task inline under Django
runserver(which uses threads):