Opened 4 years ago

Closed 17 months ago

#16700 closed Bug (fixed)

The request_started signal is not called for the first request a newly-initialized webserver receives.

Reported by: etianen Owned by: nobody
Component: Documentation Version: 1.3
Severity: Normal Keywords: app-loading
Cc: etianen Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When running Django on Apache and mod_wsgi via the WSGIHandler, the request_started signal is not sent on the first request. This problem potentially affects other server handlers too.

This problem occurs because on the first request to the server, the following sequence of actions occurs:

  1. request_started signal called
  2. Application modules are loaded, code containing signal connections is run.
  3. Request is handled
  4. request_finished signal is called

On the second request, because the application code which contains the signal handlers has been run, and the signal connections established, everything behaves has expected.

A consequence of this is that code which is expecting matched pairs of request_started and request_finished invocations for the current thread will perform unpredictably on the first request handled by the server. Subsequent requests will behave as expected. Even code that only connects to request_started will behave oddly on the first request.

The solution might be to have a module in each application which is guaranteed to be loaded before the request_started signal is called. Something like app_label/signals.py. The BaseHandler would be modified to have a load_signals() method that would iterate over the installed apps and import the signals module if present. Handler subclasses would then call this load_signals() method before the first request is handled, in a similar way to the current handling of the load_middleware() method.

Attachments (1)

bug16700.tar.gz (3.7 KB) - added by aaugustin 4 years ago.

Download all attachments as: .zip

Change History (6)

comment:1 Changed 4 years ago by etianen

  • Cc etianen added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 4 years ago by aaugustin

This is an interesting problem :)

Basically, it's up to you, the application's developer, to ensure that the code that connects the handlers to the signals runs "early enough". But if there's a pitfall, it would be useful at least to document it.

In your project, where is this code located? Could you also paste the contents of your WSGI script?

comment:3 Changed 4 years ago by aaugustin

  • Component changed from Core (Other) to Documentation
  • Triage Stage changed from Unreviewed to Accepted

If you declare your signals in the models.py of an application, this problem is reproducible with any server that uses WSGIHandlerexcept the dev server, because it imports all the models and validates them before starting. This might affect signals other than request_started, depending on where they're connected.

A workaround is to connect the request_started signal in your settings module.

Attached project demonstrates the problem with the WSGI server of the standard library. Unpack it and run: PYTHONPATH=. python bug16700/run_me.py

I suggest documenting this problem and the workaround as a known pitfall.

Changed 4 years ago by aaugustin

comment:4 Changed 4 years ago by aaugustin

This is related to #14916.

comment:5 Changed 17 months ago by aaugustin

  • Keywords app-loading added
  • Resolution set to fixed
  • Status changed from new to closed

This is fixed in Django 1.7: simply register your signals in the AppConfig.ready() method of one of your apps.

Note: See TracTickets for help on using tickets.
Back to Top