[serve] Fix a potential UnboundLocalError in `ActorReplicaWrapper.check_stopped()#63339
Merged
abrarsheikh merged 1 commit intoMay 15, 2026
Conversation
Contributor
There was a problem hiding this comment.
Code Review
This pull request initializes the "stopped" variable in the check_stopped method to prevent an UnboundLocalError. The reviewer identified a potential robustness issue where self._graceful_shutdown_ref is not checked for None before being passed to check_obj_ref_ready_nowait, which could cause a TypeError and crash the controller loop.
…k_stopped() Fix two related issues in ActorReplicaWrapper.check_stopped(): 1. The local variable 'stopped' was only assigned inside the try block or the except ValueError handler. If any other exception was raised (e.g., TypeError), 'stopped' would be undefined in the finally block and return statement, causing an UnboundLocalError that masks the root cause. 2. check_obj_ref_ready_nowait() was called without guarding against self._graceful_shutdown_ref being None. If graceful_stop() failed to set the reference (e.g., ray.get_actor raised ValueError at that time), the subsequent call would pass None to ray.wait(), raising TypeError and potentially crashing the controller reconcile loop. Fix: Initialize 'stopped = False' before the try block, and add a None check for _graceful_shutdown_ref before calling check_obj_ref_ready_nowait, consistent with the guard pattern used in check_ready() and _check_active_health_check(). Signed-off-by: chenshi5012 <chenshi5012@163.com>
d290304 to
ee4fc0b
Compare
TruongQuangPhat
pushed a commit
to cyhapun/ray-fix-issue
that referenced
this pull request
May 27, 2026
…heck_stopped() (ray-project#63339) ## Description Fix a potential `UnboundLocalError` in `ActorReplicaWrapper.check_stopped()` (`python/ray/serve/_private/deployment_state.py`). ## Related issues none ## Additional information The fix is a single-line defensive initialization. It does not change any behavior in the normal code path — `stopped` will still be correctly set to `True` by either the `try` body or the `except ValueError` handler when those paths execute successfully. ```python def check_stopped(self) -> bool: """Check if the actor has exited.""" stopped = False # Ensure 'stopped' is always defined for finally/return try: handle = ray.get_actor(self._actor_name, namespace=SERVE_NAMESPACE) stopped = check_obj_ref_ready_nowait(self._graceful_shutdown_ref) ... except ValueError: stopped = True finally: if stopped and self._placement_group is not None: ... return stopped ``` Signed-off-by: chenshi5012 <chenshi5012@163.com> Signed-off-by: phattruong <23120318@student.hcmus.edu.vn>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fix a potential
UnboundLocalErrorinActorReplicaWrapper.check_stopped()(python/ray/serve/_private/deployment_state.py).Related issues
none
Additional information
The fix is a single-line defensive initialization. It does not change any behavior in the normal code path —
stoppedwill still be correctly set toTrueby either thetrybody or theexcept ValueErrorhandler when those paths execute successfully.