Method resolution order problem in mod_wsgi 5.0.0 on Ubuntu 24.04

26 views
Skip to first unread message

Chris Siebenmann

unread,
Jan 14, 2025, 3:27:24 PMJan 14
to mod...@googlegroups.com, cks.mod...@cs.toronto.edu
I've encountered what I can only describe as an extremely weird problem
with method resolution order that happens only in mod_wsgi on Ubuntu
24.04, using the Ubuntu 24.04 version of mod_wsgi (with their Apache and
Python 3), which appears to be an unpatched 5.0.0. The specific problem is
that if you have a class that inherits from 'list,<something else>', and
the second class normally supplies a __str__ method, under mod_wsgi you
get list.__str__ instead. This first manifested in a Django application[*]
but the minimal reproduction for us is a wsgi.py application that has:

import sys

class barney:
def render(self):
return "render() in barney"
__str__ = render

class fred(list, barney):
pass

print("fred.__str__ is", fred.__str__, file=sys.stderr)

(and then the documentation example 'hello world' WSGI application()
function so that mod_wsgi is happy to start this, and will produce
output so that I know the whole thing is working correctly)

On Ubuntu 24.04's mod_wsgi, this will report on startup:
fred.__str__ is <slot wrapper '__str__' of 'list' objects>

In any other environment, including Ubuntu's mod_wsgi on 20.04 and 22.04
(which use earlier versions of mod_wsgi), this reports what we expect:
fred.__str__ is <function barney.render at 0x782909bff2e0>

(Other tests show that the 'barney' class is one of fred's parents and
other attributes are being inherited from it, even though its __str__
isn't being used.)

The actual fred.__mro__ appears to be the same between environments,
listing 'fred', 'list', 'barney', and 'object' in that order.

I'm running this test wsgi.py with a very simple WSGI configuration
in Apache:
WSGIScriptAlias /accounts /<test location>/wsgi.py
WSGIDaemonProcess accounts user=<...> group=<...>
WSGIProcessGroup accounts

Does anyone have any idea what might be going on and either how to fix
it or how to debug it?

Thanks in advance. Please let me know if I can provide more information
that would be helpful.

- cks
[*: The specific symptom we saw was that empty django.form.util.ErrorList
instances using default rendering in templates would render as
'[]' instead of blank. This was traced to them using list.__str__
for rendering instead of their custom rendering, which is set up in
the same way that 'class barney' is in this example.
]

Graham Dumpleton

unread,
Jan 14, 2025, 4:37:04 PMJan 14
to mod...@googlegroups.com, cks.mod...@cs.toronto.edu
What version of Python is Ubuntu using?

Are you definitely using system package for mod_wsgi, or have you per chance used pip to install mod_wsgi package and integrated that into your Apache instead?

Are you using a Python virtual environment?

FWIW, I don't see issues on macOS using mod_wsgi-express and Python 3.12.

Graham
> --
> You received this message because you are subscribed to the Google Groups "modwsgi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to modwsgi+u...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/modwsgi/20250114164612.4605560276%40apps0.cs.toronto.edu.

GODJonez

unread,
Jan 14, 2025, 4:37:17 PMJan 14
to mod...@googlegroups.com, cks.mod...@cs.toronto.edu

Normally, list does not define __str__ method, so the MRO resolves to the second subclass. Why does a list have __str__ in this case is a mystery to me.


Chris Siebenmann

unread,
Jan 14, 2025, 5:10:40 PMJan 14
to Graham Dumpleton, mod...@googlegroups.com, cks.mod...@cs.toronto.edu
We're definitely using the system packages for mod_wsgi (and for
Python). Ubuntu 24.04's Python is '3.12.3', and I've used lsof to verify
that the relevant Apache process has the right Python shared library
loaded; it is using '/usr/lib/x86_64-linux-gnu/libpython3.12.so.1.0'
(Ubuntu package 'libpython3.12t64', also 3.12.3), and is also using the
system mod_wsgi, '/usr/lib/apache2/modules/mod_wsgi.so-3.12'.

(Ubuntu 24.04's Apache is '2.4.58', possibly plus Ubuntu patches.)

As GODJonez notes, 'list' doesn't normally have a __str__ method;
instead it usually comes from 'object'. The Ubuntu 24.04 normal python3
binary behaves properly, with 'list.__str__' reporting:
<slot wrapper '__str__' of 'object' objects>

Within the mod_wsgi environment, 'list.__str__' is:
<slot wrapper '__str__' of 'list' objects>

(basically as expected), which as GODJonez notes explains the problem.

I built the extremely simple 'embedding Python in another application'
example from https://docs.python.org/3/extending/embedding.html and
linked it against the same libpython3.12.so.1.0 just to check, and it
reports that list.__str__ comes from 'object' as expected.

- cks

Chris Siebenmann

unread,
Jan 14, 2025, 6:20:12 PMJan 14
to mod...@googlegroups.com, Graham Dumpleton, cks.mod...@cs.toronto.edu
An update: adding 'WSGIApplicationGroup %{GLOBAL}' to my mod_wsgi
settings, which I understand forces my test WSGI pseudo-application
to run in the context of the first Python interpreter created and not a
sub-interpreter, makes the issue go away:
list.__str__ is <slot wrapper '__str__' of 'object' objects>

I'm going to see if I can hack the example 'embedding Python' C program
to use a sub-interpreter and test the behaviour there.

- cks

Chris Siebenmann

unread,
Jan 14, 2025, 7:12:18 PMJan 14
to mod...@googlegroups.com, Graham Dumpleton, cks.mod...@cs.toronto.edu
I've been able to reproduce this outside of mod_wsgi. It appears to be
an issue with the Python 3.12 in Ubuntu 24.04 when it's combined with
sub-interpreters. I have a test program,

https://www.cs.toronto.edu/~cks/vendors/ubuntu2404-python/subinterp-list-bug.c

which (if I'm using Py_NewInterpreter() properly) shows that on Ubuntu
24.04, list.__str__ gets set in the sub-interpreter. On Fedora 40, which
has Python 3.12.8, this doesn't happen, so this isn't a Python 3.12
issue in general.

Since we run only a single (Django) web application on this machine, I
think that using 'WSGIApplicationGroup %{GLOBAL}' is a viable workaround
(assuming I understand it correctly from the documentation), although
we'll need to leave ourselves a big comment in the configuration and I
believe it wouldn't be safe with multiple Django applications. Assuming
that I want to trust Ubuntu 24.04 at all after this.

Thank you, everyone.

- cks

Graham Dumpleton

unread,
Jan 15, 2025, 2:45:29 AMJan 15
to Chris Siebenmann, mod...@googlegroups.com
If running hosting multiple Django instances on same Apache, just make sure each is running in separate mod_wsgi daemon process group and you will be fine. It is recommended to force use of main interpreter context with one per daemon process group to avoid any problems with Python sub interpreters.

Not sure who you would report this issue to if it is Ubuntu specific.

Chris Siebenmann

unread,
Jan 15, 2025, 12:26:18 PMJan 15
to mod...@googlegroups.com, Chris Siebenmann
An alert person I was talking to online identified that this is a
generic Python 3.12 bug that was fixed in 3.12.5; the release notes
describe the fix as:
gh-117482: Unexpected slot wrappers are no longer created for builtin static types in subinterpreters.

linking to https://github.com/python/cpython/issues/117482

Most Linux distributions with 3.12 have a version of it that's more
recent than Ubuntu 24.04's 3.12.3, so they have the fix for this and
aren't affected. So this is an Ubuntu 24.04 bug in a sense, in that they
wouldn't have this bug if they had a more up to date 3.12.

- cks
> --
> You received this message because you are subscribed to the Google Groups "modwsgi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to modwsgi+u...@googlegroups.com.
> To view this discussion visit
> https://groups.google.com/d/msgid/modwsgi/D4C78578-9B37-4A72-B747-F0B48806A57D%40gmail.com.
Reply all
Reply to author
Forward
0 new messages