kaxil commented on code in PR #72164:
URL: https://github.com/apache/airflow/pull/72164#discussion_r4007637689
##########
task-sdk/tests/task_sdk/execution_time/test_supervisor.py:
##########
@@ -4620,8 +4703,86 @@ def
test_start_rejects_non_importable_target_under_exec(self):
@pytest.mark.usefixtures("disable_capturing")
+def test_fork_exec_bootstrap_runs_an_importable_target_end_to_end(
+ captured_logs, time_machine, monkeypatch, client_with_ti_start
+):
+ """
+ Drive the real ``os.execv`` bootstrap: the fresh interpreter runs
``_CHILD_EXEC_BOOTSTRAP``,
+ rebuilds FDs 0-3, rehydrates the target by name and hands it to
``_fork_main``.
+
+ The probe stands in for ``_subprocess_main`` rather than running the task
runner: the
+ suite stubs plugin loading in-process (conftest ``_get_plugins``), which a
bare-forked
+ child inherits and a fresh interpreter cannot.
+ """
+ from task_sdk.execution_time import exec_probe_target
Review Comment:
Take or leave: `task_sdk` is already imported at the top of this file, so
this can move up with the other imports.
##########
task-sdk/tests/task_sdk/execution_time/test_supervisor.py:
##########
@@ -4620,8 +4703,86 @@ def
test_start_rejects_non_importable_target_under_exec(self):
@pytest.mark.usefixtures("disable_capturing")
+def test_fork_exec_bootstrap_runs_an_importable_target_end_to_end(
+ captured_logs, time_machine, monkeypatch, client_with_ti_start
+):
+ """
+ Drive the real ``os.execv`` bootstrap: the fresh interpreter runs
``_CHILD_EXEC_BOOTSTRAP``,
+ rebuilds FDs 0-3, rehydrates the target by name and hands it to
``_fork_main``.
+
+ The probe stands in for ``_subprocess_main`` rather than running the task
runner: the
+ suite stubs plugin loading in-process (conftest ``_get_plugins``), which a
bare-forked
+ child inherits and a fresh interpreter cannot.
+ """
+ from task_sdk.execution_time import exec_probe_target
+
+ tests_dir =
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+ monkeypatch.setenv(
+ "PYTHONPATH", os.pathsep.join(p for p in (tests_dir,
os.environ.get("PYTHONPATH", "")) if p)
+ )
+ monkeypatch.setattr(supervisor, "_task_process_uses_exec", lambda: True)
+ # ActivitySubprocess.start only execs its own entry point; let the probe
be that entry point.
+ monkeypatch.setattr(supervisor, "_subprocess_main",
exec_probe_target.exec_probe_main)
+ time_machine.move_to(timezone.datetime(2024, 11, 7, 12, 34, 56, 78901),
tick=False)
+
+ proc = ActivitySubprocess.start(
+ dag_rel_path=os.devnull,
+ bundle_info=FAKE_BUNDLE,
+ what=TaskInstance(
+ id="4d828a62-a417-4936-a7a6-2b3fabacecab",
+ task_id="b",
+ dag_id="c",
+ run_id="d",
+ try_number=1,
+ dag_version_id=uuid7(),
+ queue="default",
+ ),
+ client=client_with_ti_start,
+ target=exec_probe_target.exec_probe_main,
+ )
+
+ assert proc.wait() == 0, captured_logs
+ assert {
+ "logger": "task.stdout",
+ "event": "exec-probe-ok",
+ "level": "info",
+ "timestamp": "2024-11-07T12:34:56.078901Z",
+ } in captured_logs
+
+
class TestChildExecMain:
- """Test the macOS fork+exec child entry point."""
+ """Test the fork+exec child entry point."""
+
+ def test_bootstrap_is_prelude_then_entry_point(self):
+ assert
supervisor._CHILD_EXEC_BOOTSTRAP.startswith(supervisor._CHILD_EXEC_PRELUDE)
+ assert
supervisor._CHILD_EXEC_BOOTSTRAP.rstrip().endswith("_child_exec_main()")
+ compile(supervisor._CHILD_EXEC_BOOTSTRAP, "<bootstrap>", "exec")
+
+ def test_prelude_survives_an_interpreter_without_ctypes(self):
+ """Without _ctypes the prelude must fall through to the logged
fallback, not kill the task."""
+ import subprocess
Review Comment:
`subprocess` is already imported at module level (line 28), so this one can
go.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]