Skip to content

[serve] Fix Windows test failure in test_serve_with_tracing by closing tracer file handles#60078

Merged
abrarsheikh merged 25 commits into
ray-project:masterfrom
landscapepainter:doyoung/resolve-serve-windows-issue-tracing
Jan 13, 2026
Merged

[serve] Fix Windows test failure in test_serve_with_tracing by closing tracer file handles#60078
abrarsheikh merged 25 commits into
ray-project:masterfrom
landscapepainter:doyoung/resolve-serve-windows-issue-tracing

Conversation

@landscapepainter

Copy link
Copy Markdown
Contributor

This fix resolves serve's window test failure:

[2026-01-12T22:52:13Z] =================================== ERRORS ====================================
--
[2026-01-12T22:52:13Z] _______ ERROR at teardown of test_deployment_remote_calls_with_tracing ________
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z]     @pytest.fixture
[2026-01-12T22:52:13Z]     def cleanup_spans():
[2026-01-12T22:52:13Z]         """Cleanup temporary spans_dir folder at beginning and end of test."""
[2026-01-12T22:52:13Z]         if os.path.exists(spans_dir):
[2026-01-12T22:52:13Z]             shutil.rmtree(spans_dir)
[2026-01-12T22:52:13Z]         os.makedirs(spans_dir, exist_ok=True)
[2026-01-12T22:52:13Z]         yield
[2026-01-12T22:52:13Z]         # Enable tracing only sets up tracing once per driver process.
[2026-01-12T22:52:13Z]         # We set ray.__traced__ to False here so that each
[2026-01-12T22:52:13Z]         # test will re-set up tracing.
[2026-01-12T22:52:13Z]         ray.__traced__ = False
[2026-01-12T22:52:13Z]         if os.path.exists(spans_dir):
[2026-01-12T22:52:13Z] >           shutil.rmtree(spans_dir)
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z] python\ray\serve\tests\test_serve_with_tracing.py:30:
[2026-01-12T22:52:13Z] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[2026-01-12T22:52:13Z] C:\Miniconda3\lib\shutil.py:750: in rmtree
[2026-01-12T22:52:13Z]     return _rmtree_unsafe(path, onerror)
[2026-01-12T22:52:13Z] C:\Miniconda3\lib\shutil.py:620: in _rmtree_unsafe
[2026-01-12T22:52:13Z]     onerror(os.unlink, fullname, sys.exc_info())
[2026-01-12T22:52:13Z] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z] path = '/tmp/spans/'
[2026-01-12T22:52:13Z] onerror = <function rmtree.<locals>.onerror at 0x000002C0FFBBDA20>
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z]     def _rmtree_unsafe(path, onerror):
[2026-01-12T22:52:13Z]         try:
[2026-01-12T22:52:13Z]             with os.scandir(path) as scandir_it:
[2026-01-12T22:52:13Z]                 entries = list(scandir_it)
[2026-01-12T22:52:13Z]         except OSError:
[2026-01-12T22:52:13Z]             onerror(os.scandir, path, sys.exc_info())
[2026-01-12T22:52:13Z]             entries = []
[2026-01-12T22:52:13Z]         for entry in entries:
[2026-01-12T22:52:13Z]             fullname = entry.path
[2026-01-12T22:52:13Z]             if _rmtree_isdir(entry):
[2026-01-12T22:52:13Z]                 try:
[2026-01-12T22:52:13Z]                     if entry.is_symlink():
[2026-01-12T22:52:13Z]                         # This can only happen if someone replaces
[2026-01-12T22:52:13Z]                         # a directory with a symlink after the call to
[2026-01-12T22:52:13Z]                         # os.scandir or entry.is_dir above.
[2026-01-12T22:52:13Z]                         raise OSError("Cannot call rmtree on a symbolic link")
[2026-01-12T22:52:13Z]                 except OSError:
[2026-01-12T22:52:13Z]                     onerror(os.path.islink, fullname, sys.exc_info())
[2026-01-12T22:52:13Z]                     continue
[2026-01-12T22:52:13Z]                 _rmtree_unsafe(fullname, onerror)
[2026-01-12T22:52:13Z]             else:
[2026-01-12T22:52:13Z]                 try:
[2026-01-12T22:52:13Z] >                   os.unlink(fullname)
[2026-01-12T22:52:13Z] E                   PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: '/tmp/spans/15464.txt'
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z] C:\Miniconda3\lib\shutil.py:618: PermissionError

Cause: The setup_local_tmp_tracing.py module opens a file handle for the ConsoleSpanExporter that is never explicitly closed. On Windows, files cannot be deleted while they're open, causing shutil.rmtree to fail with PermissionError: [WinError 32] during the cleanup_spans fixture teardown.

Fix: Added trace.get_tracer_provider().shutdown() in the ray_serve_with_tracing fixture teardown to properly flush and close the span exporter's file handles before the cleanup fixture attempts to delete the spans directory.

Signed-off-by: doyoung <doyoung@anyscale.com>
@landscapepainter landscapepainter requested a review from a team as a code owner January 13, 2026 01:03
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@landscapepainter landscapepainter added the go add ONLY when ready to merge, run all tests label Jan 13, 2026
@ray-gardener ray-gardener Bot added serve Ray Serve Related Issue windows labels Jan 13, 2026
Comment on lines +43 to +45
tracer_provider = trace.get_tracer_provider()
if hasattr(tracer_provider, "shutdown"):
tracer_provider.shutdown()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this should happen in ray core. @ZacAttack wdyt?

@abrarsheikh abrarsheikh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unblocking CI for now.

@abrarsheikh abrarsheikh merged commit 3feb429 into ray-project:master Jan 13, 2026
6 checks passed
rushikeshadhav pushed a commit to rushikeshadhav/ray that referenced this pull request Jan 14, 2026
…g tracer file handles (ray-project#60078)

This fix resolves serve's window test failure:
```
[2026-01-12T22:52:13Z] =================================== ERRORS ====================================
--
[2026-01-12T22:52:13Z] _______ ERROR at teardown of test_deployment_remote_calls_with_tracing ________
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z]     @pytest.fixture
[2026-01-12T22:52:13Z]     def cleanup_spans():
[2026-01-12T22:52:13Z]         """Cleanup temporary spans_dir folder at beginning and end of test."""
[2026-01-12T22:52:13Z]         if os.path.exists(spans_dir):
[2026-01-12T22:52:13Z]             shutil.rmtree(spans_dir)
[2026-01-12T22:52:13Z]         os.makedirs(spans_dir, exist_ok=True)
[2026-01-12T22:52:13Z]         yield
[2026-01-12T22:52:13Z]         # Enable tracing only sets up tracing once per driver process.
[2026-01-12T22:52:13Z]         # We set ray.__traced__ to False here so that each
[2026-01-12T22:52:13Z]         # test will re-set up tracing.
[2026-01-12T22:52:13Z]         ray.__traced__ = False
[2026-01-12T22:52:13Z]         if os.path.exists(spans_dir):
[2026-01-12T22:52:13Z] >           shutil.rmtree(spans_dir)
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z] python\ray\serve\tests\test_serve_with_tracing.py:30:
[2026-01-12T22:52:13Z] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[2026-01-12T22:52:13Z] C:\Miniconda3\lib\shutil.py:750: in rmtree
[2026-01-12T22:52:13Z]     return _rmtree_unsafe(path, onerror)
[2026-01-12T22:52:13Z] C:\Miniconda3\lib\shutil.py:620: in _rmtree_unsafe
[2026-01-12T22:52:13Z]     onerror(os.unlink, fullname, sys.exc_info())
[2026-01-12T22:52:13Z] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z] path = '/tmp/spans/'
[2026-01-12T22:52:13Z] onerror = <function rmtree.<locals>.onerror at 0x000002C0FFBBDA20>
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z]     def _rmtree_unsafe(path, onerror):
[2026-01-12T22:52:13Z]         try:
[2026-01-12T22:52:13Z]             with os.scandir(path) as scandir_it:
[2026-01-12T22:52:13Z]                 entries = list(scandir_it)
[2026-01-12T22:52:13Z]         except OSError:
[2026-01-12T22:52:13Z]             onerror(os.scandir, path, sys.exc_info())
[2026-01-12T22:52:13Z]             entries = []
[2026-01-12T22:52:13Z]         for entry in entries:
[2026-01-12T22:52:13Z]             fullname = entry.path
[2026-01-12T22:52:13Z]             if _rmtree_isdir(entry):
[2026-01-12T22:52:13Z]                 try:
[2026-01-12T22:52:13Z]                     if entry.is_symlink():
[2026-01-12T22:52:13Z]                         # This can only happen if someone replaces
[2026-01-12T22:52:13Z]                         # a directory with a symlink after the call to
[2026-01-12T22:52:13Z]                         # os.scandir or entry.is_dir above.
[2026-01-12T22:52:13Z]                         raise OSError("Cannot call rmtree on a symbolic link")
[2026-01-12T22:52:13Z]                 except OSError:
[2026-01-12T22:52:13Z]                     onerror(os.path.islink, fullname, sys.exc_info())
[2026-01-12T22:52:13Z]                     continue
[2026-01-12T22:52:13Z]                 _rmtree_unsafe(fullname, onerror)
[2026-01-12T22:52:13Z]             else:
[2026-01-12T22:52:13Z]                 try:
[2026-01-12T22:52:13Z] >                   os.unlink(fullname)
[2026-01-12T22:52:13Z] E                   PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: '/tmp/spans/15464.txt'
[2026-01-12T22:52:13Z]
[2026-01-12T22:52:13Z] C:\Miniconda3\lib\shutil.py:618: PermissionError
```

**Cause:** The `setup_local_tmp_tracing.py` module opens a file handle
for the `ConsoleSpanExporter` that is never explicitly closed. On
Windows, files cannot be deleted while they're open, causing
`shutil.rmtree` to fail with `PermissionError: [WinError 32]` during the
`cleanup_spans` fixture teardown.

**Fix:** Added `trace.get_tracer_provider().shutdown()` in the
`ray_serve_with_tracing` fixture teardown to properly flush and close
the span exporter's file handles before the cleanup fixture attempts to
delete the spans directory.

---------

Signed-off-by: doyoung <doyoung@anyscale.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

go add ONLY when ready to merge, run all tests serve Ray Serve Related Issue windows

Development

Successfully merging this pull request may close these issues.

2 participants