| py = '3.11'
|
| tmp_path = PosixPath('/tmp/pytest-of-root/pytest-0/test_attach_container_like_3_11')
|
| prefix = ['unshare', '-p', '-f', '-r']
|
|
|
| @pytest.mark.parametrize("prefix", [[], ["unshare", "-p", "-f", "-r"]])
|
| @pytest.mark.skipif(platform.system() != "Linux", reason="Linux only")
|
| @requires_sudo
|
| @allpythons()
|
| def test_attach_container_like(py, tmp_path, prefix):
|
| """Test in container-like conditions.
|
|
|
| We test that we can still attach Austin to a running process even if we
|
| don't have access to the binary files to determine the location of the
|
| symbols. We also test against an interpreter started in a different PID
|
| namespace to emulate a container as closely as possible.
|
| """
|
| venv_path = tmp_path / ".venv"
|
| p = run_python(py, "-m", "venv", "--copies", str(venv_path))
|
| p.wait(30)
|
| assert 0 == p.returncode, "Virtual environment was created successfully"
|
|
|
| env = os.environ.copy()
|
| env["LD_LIBRARY_PATH"] = str(venv_path / "lib")
|
| env["PATH"] = str(venv_path / "bin") + os.pathsep + env["PATH"]
|
| # Give the target enough lifetime (sleepy.py sleeps `interval` seconds
|
| # twice) that a successful attach -- which then blocks sampling until
|
| # the target exits, since "-Cp" has no exposure limit -- has real time
|
| # left to collect a useful sample, rather than attaching moments before
|
| # the target's natural death and coming back empty.
|
| with run_python(
|
| py, target("sleepy.py"), "10", env=env, prefix=prefix, sleep_after=0.5
|
| ) as p:
|
| rmtree(venv_path)
|
|
|
| # With a prefix like "unshare -p -f -r", the PID we attach to is the
|
| # launcher, not the exec'd Python interpreter -- austin's own "-C"
|
| # fallback needs that child to have actually forked+exec'd by the
|
| # time it scans for it. A failed attach returns fast (no child
|
| # found yet), so retry_until gets several real attempts cheaply;
|
| # poll instead of trusting a single fixed-delay snapshot.
|
| result = retry_until(
|
| lambda: austin("-Cp", str(p.pid)),
|
| lambda r: has_frame(r.samples, filename="sleepy.py", function="<module>"),
|
| )
|
| assert result.returncode == 0, result.stderr or result.stdout
|
|
|
| ts = threads(result.samples)
|
| > assert len(ts) == 1, result.stderr or result.stdout
|
| E AssertionError: [1m _ _ [0m
|
| E [1m __ _ _ _ __| |_(_)_ _ [0m
|
| E [1m/ _` | || (_-< _| | ' \ [0m
|
| E [1m\__,_|\_,_/__/\__|_|_||_| [0m [1;36m4.1.0 [0m [gcc 13.3.0]
|
| E 👽 Parent is not a Python process.
|
| E
|
| E 😣 No samples collected.
|
| E
|
| E assert 0 == 1
|
| E + where 0 = len(set())
|
|
|
| test/functional/test_attach.py:259: AssertionError
|