diff --git a/gunicorn/ctl/handlers.py b/gunicorn/ctl/handlers.py index dedf349f..690c9842 100644 --- a/gunicorn/ctl/handlers.py +++ b/gunicorn/ctl/handlers.py @@ -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 [] diff --git a/gunicorn/dirty/protocol.py b/gunicorn/dirty/protocol.py index b6e996af..8091b23f 100644 --- a/gunicorn/dirty/protocol.py +++ b/gunicorn/dirty/protocol.py @@ -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}")