Apache/mod_wsgi Process Hanging After SciPy Installation: Debugging Django Freeze Issues


2 views

When you installed SciPy 0.12.0 via pip on your CentOS 6.4 server running Apache 2.2.15 and mod_wsgi 3.2, you essentially introduced a stealthy performance killer. The absence of error logs makes this particularly frustrating - the Django 1.5.1 (Python 2.6.6) application simply stops responding without any visible traces.

The key indicators we're seeing:

  • Normal operation through manage.py shell
  • No errors in Apache or system logs
  • Child httpd processes hanging indefinitely
  • Only manifests after SciPy installation

First, let's examine the process memory footprint:

# Monitor Apache processes
ps aux | grep httpd | grep -v grep | awk '{print $2, $4, $5, $6, $11}'

# Check memory limits
cat /proc/$(pgrep -f mod_wsgi)/limits

# Alternative: use pmap for specific process
pmap -x $(pgrep -f mod_wsgi) | less

SciPy's numerical computations often use threading internally. When running under mod_wsgi in embedded mode, this can lead to:

  • Thread deadlocks during numpy/scipy operations
  • Memory allocation conflicts
  • Signal handling problems

Modify your Apache configuration to use mod_wsgi daemon mode:

WSGIDaemonProcess myapp processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup myapp
WSGIApplicationGroup %{GLOBAL}

Consider these architectural changes:

# Option 1: Move numerical computations to a microservice
# (e.g., using Celery with a dedicated worker)

# Option 2: Use WSGI script file with proper initialization
import os
os.environ['OMP_NUM_THREADS'] = '1'
os.environ['MKL_NUM_THREADS'] = '1'

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Create a test endpoint to validate the fix:

# views.py
from django.http import JsonResponse
import scipy

def debug_view(request):
    try:
        import numpy as np
        from scipy.linalg import solve
        a = np.array([[3,1], [1,2]])
        b = np.array([9,8])
        x = solve(a, b)
        return JsonResponse({'status': 'success', 'result': x.tolist()})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': str(e)})

When scipy 0.12.0 enters the picture on CentOS 6.4 with Apache 2.2.15/mod_wsgi 3.2, we face a peculiar situation where the Django application becomes completely unresponsive. The server spawns child processes that hang indefinitely without any error logs - not in Apache's error_log, vhost logs, or system logs.

The symptoms manifest when:

# This works fine
python manage.py shell
>>> from myapp.models import MyModel
>>> MyModel.objects.all() # Successful query

# But the same code through mod_wsgi causes complete freeze
# No response, no errors, just hanging processes

scipy's numerical libraries perform aggressive memory pre-allocation that can conflict with mod_wsgi's process management. The issue becomes particularly acute when using the default prefork MPM in Apache.

To verify if this is indeed the problem:

# Create a test view
def memory_test(request):
    import resource
    soft, hard = resource.getrlimit(resource.RLIMIT_AS)
    return HttpResponse(f"Memory limits: Soft={soft}, Hard={hard}")

We need to modify the WSGI configuration to properly handle scipy's memory demands:

# In your wsgi.py
import os
import numpy
import scipy
from django.core.wsgi import get_wsgi_application

# Critical initialization order
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
numpy.set_printoptions(threshold=5)
scipy.random.seed()

application = get_wsgi_application()

Add these directives to your VirtualHost:

WSGIApplicationGroup %{GLOBAL}
WSGIDaemonProcess myapp processes=2 threads=15 display-name=%{GROUP} 
WSGIProcessGroup myapp

For more reliable isolation:

# Dockerfile snippet
FROM centos:6
RUN yum install -y httpd mod_wsgi
RUN pip install scipy==0.12.0
COPY . /var/www/html
EXPOSE 80
CMD ["httpd", "-D", "FOREGROUND"]

When working with scientific Python packages:

  1. Always test in staging with identical server configurations
  2. Consider using WSGI application groups for isolation
  3. Monitor memory usage during package imports