mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +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
 | 
			
		||||
    placeholder_open_graph_description: Optional[str] = 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)
 | 
			
		||||
    ignored_parameters: Set[str] = field(default_factory=set)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ import os
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
import time
 | 
			
		||||
import weakref
 | 
			
		||||
from contextlib import contextmanager
 | 
			
		||||
from functools import wraps
 | 
			
		||||
from typing import (
 | 
			
		||||
@@ -310,7 +311,6 @@ class HostRequestMock(HttpRequest):
 | 
			
		||||
            self.POST[key] = str(post_data[key])
 | 
			
		||||
            self.method = "POST"
 | 
			
		||||
 | 
			
		||||
        self._tornado_handler = DummyHandler()
 | 
			
		||||
        self._log_data: Dict[str, Any] = {}
 | 
			
		||||
        if meta_data is None:
 | 
			
		||||
            self.META = {"PATH_INFO": "test"}
 | 
			
		||||
@@ -324,7 +324,7 @@ class HostRequestMock(HttpRequest):
 | 
			
		||||
        request_notes_map[self] = ZulipRequestNotes(
 | 
			
		||||
            client_name="",
 | 
			
		||||
            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,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import logging
 | 
			
		||||
import urllib
 | 
			
		||||
import weakref
 | 
			
		||||
from typing import Any, Dict, List
 | 
			
		||||
 | 
			
		||||
import tornado.web
 | 
			
		||||
@@ -116,7 +117,7 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
 | 
			
		||||
 | 
			
		||||
        # Provide a way for application code to access this handler
 | 
			
		||||
        # given the HttpRequest object.
 | 
			
		||||
        get_request_notes(request).tornado_handler = self
 | 
			
		||||
        get_request_notes(request).tornado_handler = weakref.ref(self)
 | 
			
		||||
 | 
			
		||||
        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.tornado.event_queue import fetch_events, get_client_descriptor, process_notification
 | 
			
		||||
from zerver.tornado.exceptions import BadEventQueueIdError
 | 
			
		||||
from zerver.tornado.handlers import AsyncDjangoHandler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@internal_notify_view(True)
 | 
			
		||||
@@ -111,7 +110,8 @@ def get_events_backend(
 | 
			
		||||
    # Extract the Tornado handler from the request
 | 
			
		||||
    tornado_handler = get_request_notes(request).tornado_handler
 | 
			
		||||
    assert tornado_handler is not None
 | 
			
		||||
    handler: AsyncDjangoHandler = tornado_handler
 | 
			
		||||
    handler = tornado_handler()
 | 
			
		||||
    assert handler is not None
 | 
			
		||||
 | 
			
		||||
    if user_client is None:
 | 
			
		||||
        valid_user_client = get_request_notes(request).client
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user