Skip to content
Open
34 changes: 34 additions & 0 deletions .riot/requirements/111cc29.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile --allow-unsafe --no-annotate .riot/requirements/111cc29.in
#
attrs==25.3.0
coverage[toml]==7.10.6
exceptiongroup==1.3.0
gunicorn==23.0.0
hypothesis==6.45.0
iniconfig==2.1.0
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
lz4==4.4.4
mock==5.2.0
opentracing==2.4.0
packaging==25.0
pluggy==1.6.0
py-cpuinfo==8.0.0
pygments==2.19.2
pytest==8.4.2
pytest-asyncio==0.21.1
pytest-benchmark==5.1.0
pytest-cov==6.3.0
pytest-cpp==2.6.0
pytest-mock==3.15.0
pytest-randomly==3.16.0
referencing==0.36.2
rpds-py==0.27.1
sortedcontainers==2.4.0
tomli==2.2.1
typing-extensions==4.15.0
uwsgi==2.0.29
32 changes: 32 additions & 0 deletions .riot/requirements/133fa5b.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --allow-unsafe --no-annotate .riot/requirements/133fa5b.in
#
attrs==25.3.0
coverage[toml]==7.10.6
gunicorn==23.0.0
hypothesis==6.45.0
iniconfig==2.1.0
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
lz4==4.4.4
mock==5.2.0
opentracing==2.4.0
packaging==25.0
pluggy==1.6.0
py-cpuinfo==8.0.0
pygments==2.19.2
pytest==8.4.2
pytest-asyncio==0.21.1
pytest-benchmark==5.1.0
pytest-cov==6.3.0
pytest-cpp==2.6.0
pytest-mock==3.15.0
pytest-randomly==3.16.0
referencing==0.36.2
rpds-py==0.27.1
sortedcontainers==2.4.0
typing-extensions==4.15.0
uwsgi==2.0.29
37 changes: 37 additions & 0 deletions .riot/requirements/145beea.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
# This file is autogenerated by pip-compile with Python 3.8
# by the following command:
#
# pip-compile --allow-unsafe --no-annotate .riot/requirements/145beea.in
#
attrs==25.3.0
coverage[toml]==7.6.1
exceptiongroup==1.3.0
gunicorn==23.0.0
hypothesis==6.45.0
importlib-metadata==8.5.0
importlib-resources==6.4.5
iniconfig==2.1.0
jsonschema==4.23.0
jsonschema-specifications==2023.12.1
lz4==4.3.3
mock==5.2.0
opentracing==2.4.0
packaging==25.0
pkgutil-resolve-name==1.3.10
pluggy==1.5.0
py-cpuinfo==8.0.0
pytest==8.3.5
pytest-asyncio==0.21.1
pytest-benchmark==4.0.0
pytest-cov==5.0.0
pytest-cpp==2.6.0
pytest-mock==3.14.1
pytest-randomly==3.15.0
referencing==0.35.1
rpds-py==0.20.1
sortedcontainers==2.4.0
tomli==2.2.1
typing-extensions==4.13.2
uwsgi==2.0.29
zipp==3.20.2
31 changes: 31 additions & 0 deletions .riot/requirements/1e66025.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile --allow-unsafe --no-annotate .riot/requirements/1e66025.in
#
attrs==25.3.0
coverage[toml]==7.10.6
gunicorn==23.0.0
hypothesis==6.45.0
iniconfig==2.1.0
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
lz4==4.4.4
mock==5.2.0
opentracing==2.4.0
packaging==25.0
pluggy==1.6.0
py-cpuinfo==8.0.0
pygments==2.19.2
pytest==8.4.2
pytest-asyncio==0.21.1
pytest-benchmark==5.1.0
pytest-cov==6.3.0
pytest-cpp==2.6.0
pytest-mock==3.15.0
pytest-randomly==3.16.0
referencing==0.36.2
rpds-py==0.27.1
sortedcontainers==2.4.0
uwsgi==2.0.29
36 changes: 36 additions & 0 deletions .riot/requirements/8a26afe.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --allow-unsafe --no-annotate .riot/requirements/8a26afe.in
#
attrs==25.3.0
coverage[toml]==7.10.6
exceptiongroup==1.3.0
gunicorn==23.0.0
hypothesis==6.45.0
importlib-metadata==8.7.0
iniconfig==2.1.0
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
lz4==4.4.4
mock==5.2.0
opentracing==2.4.0
packaging==25.0
pluggy==1.6.0
py-cpuinfo==8.0.0
pygments==2.19.2
pytest==8.4.2
pytest-asyncio==0.21.1
pytest-benchmark==5.1.0
pytest-cov==6.3.0
pytest-cpp==2.6.0
pytest-mock==3.15.0
pytest-randomly==3.16.0
referencing==0.36.2
rpds-py==0.27.1
sortedcontainers==2.4.0
tomli==2.2.1
typing-extensions==4.15.0
uwsgi==2.0.29
zipp==3.23.0
32 changes: 32 additions & 0 deletions .riot/requirements/ba22367.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --allow-unsafe --no-annotate .riot/requirements/ba22367.in
#
attrs==25.3.0
coverage[toml]==7.10.6
gunicorn==23.0.0
hypothesis==6.45.0
iniconfig==2.1.0
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
lz4==4.4.4
mock==5.2.0
opentracing==2.4.0
packaging==25.0
pluggy==1.6.0
py-cpuinfo==8.0.0
pygments==2.19.2
pytest==8.4.2
pytest-asyncio==0.21.1
pytest-benchmark==5.1.0
pytest-cov==6.3.0
pytest-cpp==2.6.0
pytest-mock==3.15.0
pytest-randomly==3.16.0
referencing==0.36.2
rpds-py==0.27.1
sortedcontainers==2.4.0
typing-extensions==4.15.0
uwsgi==2.0.29
9 changes: 9 additions & 0 deletions ddtrace/internal/uwsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ def check_uwsgi(worker_callback: Optional[Callable] = None, atexit: Optional[Cal
msg = "enable-threads option must be set to true, or a positive number of threads must be set"
raise uWSGIConfigError(msg)

if (
hasattr(uwsgi, "version_info")
and uwsgi.version_info < (2, 0, 30)
and (uwsgi.opt.get("lazy-apps") or uwsgi.opt.get("lazy"))
and not uwsgi.opt.get("skip-atexit")
):
msg = "skip-atexit option must be set when lazy-apps or lazy is set for uwsgi<2.0.30, see https://github.com/unbit/uwsgi/pull/2726"
raise uWSGIConfigError(msg)

# If uwsgi has more than one process, it is running in prefork operational mode: uwsgi is going to fork multiple
# sub-processes.
# If lazy-app is enabled, then the app is loaded in each subprocess independently. This is fine.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
uWSGI: It is now required to specify ``--skip-atexit`` when ``--lazy`` or
``--lazy-apps`` is set on uWSGI<2.0.30. It is to prevent crashes from
native extension modules. See https://github.com/unbit/uwsgi/pull/2726
for details.

5 changes: 5 additions & 0 deletions riotfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3301,6 +3301,11 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT
"pytest-randomly": latest,
},
venvs=[
Venv(
command="python -m pytest {cmdargs} tests/profiling_v2/test_uwsgi.py",
pys=select_pys(),
pkgs={"uwsgi": "<2.0.30"},
),
# Python 3.8 + 3.9
Venv(
pys=["3.8", "3.9"],
Expand Down
20 changes: 20 additions & 0 deletions tests/profiling_v2/test_uwsgi.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from importlib.metadata import version
import os
import re
import signal
Expand Down Expand Up @@ -170,3 +171,22 @@ def test_uwsgi_threads_processes_no_primary_lazy_apps(uwsgi, tmp_path, monkeypat
profile = pprof_utils.parse_newest_profile("%s.%d" % (filename, pid))
samples = pprof_utils.get_samples_with_value_type(profile, "wall-time")
assert len(samples) > 0


@pytest.mark.skipif(
tuple(int(x) for x in version("uwsgi").split(".")) >= (2, 0, 30),
reason="uwsgi>=2.0.30 does not require --skip-atexit",
)
def test_uwsgi_require_skip_atexit_when_lazy(uwsgi, tmp_path, monkeypatch):
filename = str(tmp_path / "uwsgi.pprof")
monkeypatch.setenv("DD_PROFILING_OUTPUT_PPROF", filename)
monkeypatch.setenv("DD_PROFILING_UPLOAD_INTERVAL", "1")
proc = uwsgi("--enable-threads", "--processes", "2", "--lazy-apps")
stdout, _ = proc.communicate()
assert proc.wait() != 0
assert b"skip-atexit option must be set" in stdout

proc = uwsgi("--enable-threads", "--processes", "2", "--lazy")
stdout, _ = proc.communicate()
assert proc.wait() != 0
assert b"skip-atexit option must be set" in stdout
Loading