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:
- Always test in staging with identical server configurations
- Consider using WSGI application groups for isolation
- Monitor memory usage during package imports