-
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Description
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'srunserver) - The warm/cold shutdown distinction is erased
- The
REMAP_SIGTERMconfiguration 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
- I have read the relevant section in the
contribution guide
on reporting bugs. - I have checked the issues list
for similar or identical bug reports. - I have checked the pull requests list
for existing proposed fixes. - I have checked the commit log
to find out if the bug was already fixed in the master branch. - I have included all related issues and possible duplicate issues
in this issue (If there are none, check this box anyway).
Mandatory Debugging Information
- I have included the output of
celery -A proj reportin the issue.
(if you are not able to do this, then at least specify the Celery
version affected). - I have verified that the issue exists against the
masterbranch of Celery. - I have included the contents of
pip freezein the issue. - I have included all the versions of all the external dependencies required
to reproduce this bug.
Related Issues and Possible Duplicates
Related Issues
Possible Duplicates
- None
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