mirror of
https://github.com/zulip/zulip.git
synced 2025-11-14 02:48:00 +00:00
request: Weaken ZulipRequestNotes.tornado_handler reference.
This prevents a memory leak arising from Python’s inability to collect a reference cycle from a WeakKeyDictionary value to its key (https://bugs.python.org/issue44680). Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
committed by
Tim Abbott
parent
7c32134fb5
commit
6564b258f1
@@ -62,7 +62,9 @@ class ZulipRequestNotes:
|
|||||||
error_format: Optional[str] = None
|
error_format: Optional[str] = None
|
||||||
placeholder_open_graph_description: Optional[str] = None
|
placeholder_open_graph_description: Optional[str] = None
|
||||||
saved_response: Optional[HttpResponse] = None
|
saved_response: Optional[HttpResponse] = None
|
||||||
tornado_handler: Optional["handlers.AsyncDjangoHandler"] = None
|
# tornado_handler is a weak reference to work around a memory leak
|
||||||
|
# in WeakKeyDictionary (https://bugs.python.org/issue44680).
|
||||||
|
tornado_handler: Optional["weakref.ReferenceType[handlers.AsyncDjangoHandler]"] = None
|
||||||
processed_parameters: Set[str] = field(default_factory=set)
|
processed_parameters: Set[str] = field(default_factory=set)
|
||||||
ignored_parameters: Set[str] = field(default_factory=set)
|
ignored_parameters: Set[str] = field(default_factory=set)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import os
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
import weakref
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from typing import (
|
from typing import (
|
||||||
@@ -310,7 +311,6 @@ class HostRequestMock(HttpRequest):
|
|||||||
self.POST[key] = str(post_data[key])
|
self.POST[key] = str(post_data[key])
|
||||||
self.method = "POST"
|
self.method = "POST"
|
||||||
|
|
||||||
self._tornado_handler = DummyHandler()
|
|
||||||
self._log_data: Dict[str, Any] = {}
|
self._log_data: Dict[str, Any] = {}
|
||||||
if meta_data is None:
|
if meta_data is None:
|
||||||
self.META = {"PATH_INFO": "test"}
|
self.META = {"PATH_INFO": "test"}
|
||||||
@@ -324,7 +324,7 @@ class HostRequestMock(HttpRequest):
|
|||||||
request_notes_map[self] = ZulipRequestNotes(
|
request_notes_map[self] = ZulipRequestNotes(
|
||||||
client_name="",
|
client_name="",
|
||||||
log_data={},
|
log_data={},
|
||||||
tornado_handler=tornado_handler,
|
tornado_handler=None if tornado_handler is None else weakref.ref(tornado_handler),
|
||||||
client=get_client(client_name) if client_name is not None else None,
|
client=get_client(client_name) if client_name is not None else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import urllib
|
import urllib
|
||||||
|
import weakref
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
import tornado.web
|
import tornado.web
|
||||||
@@ -116,7 +117,7 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
|||||||
|
|
||||||
# Provide a way for application code to access this handler
|
# Provide a way for application code to access this handler
|
||||||
# given the HttpRequest object.
|
# given the HttpRequest object.
|
||||||
get_request_notes(request).tornado_handler = self
|
get_request_notes(request).tornado_handler = weakref.ref(self)
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ from zerver.lib.validator import (
|
|||||||
from zerver.models import Client, UserProfile, get_client, get_user_profile_by_id
|
from zerver.models import Client, UserProfile, get_client, get_user_profile_by_id
|
||||||
from zerver.tornado.event_queue import fetch_events, get_client_descriptor, process_notification
|
from zerver.tornado.event_queue import fetch_events, get_client_descriptor, process_notification
|
||||||
from zerver.tornado.exceptions import BadEventQueueIdError
|
from zerver.tornado.exceptions import BadEventQueueIdError
|
||||||
from zerver.tornado.handlers import AsyncDjangoHandler
|
|
||||||
|
|
||||||
|
|
||||||
@internal_notify_view(True)
|
@internal_notify_view(True)
|
||||||
@@ -111,7 +110,8 @@ def get_events_backend(
|
|||||||
# Extract the Tornado handler from the request
|
# Extract the Tornado handler from the request
|
||||||
tornado_handler = get_request_notes(request).tornado_handler
|
tornado_handler = get_request_notes(request).tornado_handler
|
||||||
assert tornado_handler is not None
|
assert tornado_handler is not None
|
||||||
handler: AsyncDjangoHandler = tornado_handler
|
handler = tornado_handler()
|
||||||
|
assert handler is not None
|
||||||
|
|
||||||
if user_client is None:
|
if user_client is None:
|
||||||
valid_user_client = get_request_notes(request).client
|
valid_user_client = get_request_notes(request).client
|
||||||
|
|||||||
Reference in New Issue
Block a user