fix(ctl): properly encode/decode MSG_TYPE_STATUS for dirty worker query

- Add encode_status method to BinaryProtocol
- Use arbiter.dirty_arbiter.socket_path instead of env var when available
This commit is contained in:
Benoit Chesneau 2026-02-13 01:56:39 +01:00
parent 3e6d6b94c5
commit be27ed4036
2 changed files with 28 additions and 3 deletions

View File

@ -474,7 +474,13 @@ class CommandHandlers:
List of dirty worker info dicts, or empty list on error
"""
import socket
dirty_socket_path = os.environ.get('GUNICORN_DIRTY_SOCKET')
# Get socket path from arbiter object or environment
dirty_socket_path = None
if hasattr(self.arbiter, 'dirty_arbiter') and self.arbiter.dirty_arbiter:
dirty_socket_path = getattr(self.arbiter.dirty_arbiter, 'socket_path', None)
if not dirty_socket_path:
dirty_socket_path = os.environ.get('GUNICORN_DIRTY_SOCKET')
if not dirty_socket_path:
return []
@ -500,8 +506,10 @@ class CommandHandlers:
data = response.get("data", {})
return data.get("workers", [])
except Exception:
pass
except Exception as e:
# Log error for debugging
if hasattr(self.arbiter, 'log') and self.arbiter.log:
self.arbiter.log.debug("Failed to query dirty workers: %s", e)
return []

View File

@ -277,6 +277,21 @@ class BinaryProtocol:
header = BinaryProtocol.encode_header(MSG_TYPE_END, request_id, 0)
return header
@staticmethod
def encode_status(request_id: int) -> bytes:
"""
Encode a status query message.
Args:
request_id: Request identifier
Returns:
bytes: Complete message (header + empty payload)
"""
# Status query has empty payload
header = BinaryProtocol.encode_header(MSG_TYPE_STATUS, request_id, 0)
return header
@staticmethod
def encode_stash(request_id: int, op: int, table: str,
key=None, value=None, pattern=None) -> bytes:
@ -586,6 +601,8 @@ class BinaryProtocol:
message.get("value"),
message.get("pattern")
)
elif msg_type == MSG_TYPE_STATUS:
return BinaryProtocol.encode_status(request_id)
else:
raise DirtyProtocolError(f"Unhandled message type: {msg_type}")