Расширьте python/django с помощью c и mod_wsgi с помощью apache

У меня есть вопрос о расширении python с помощью кода C и mod_wsgi.

У меня есть приложение django на сервере apache, которое запрашивает базу данных postgresql для создания отчетов. В некоторых отчетах система создает csv-файл с результатами. Чтобы создать этот csv-файл, система иногда должна обрабатывать более двухсот тысяч регистров с помощью python, что, очевидно, очень медленно. Чтобы ускорить это, мы запрограммировали модуль c, который выполняет эту работу и увеличивает скорость во много раз. Мы пробовали с ctypes и создали модуль python с c, оба отлично работают на сервере выполнения, но вылетают при выполнении с apache и mod_wsgi.

Ошибка в httpd-error.log:

[Среда, 27 июля 02:33:52 2011] [уведомление] дочерний pid 44657 сигнал выхода Ошибка сегментации (11)

Любое предложение?

Код:

# Creates the HttpResponse object with the appropriate CSV header.
response = HttpResponse(mimetype='application/x-zip-compressed')
response['Content-Disposition'] = \
    'attachment; filename=' + filename + '.zip'

p0 = 'descarga_' + str(datetime.today()) + '.csv'

p1 = settings.DATABASES['default']['NAME']
p2 = settings.DATABASES['default']['USER']

#lib.generar(string_at(p0),p1,p2,string_at(str(init)),string_at(str(end)),string_at(str(provider)))

import generador
generador.generar(p0,p1,p2,str(init),str(end),str(provider))

Он падает после того, как мы вызываем generador.generar(), который является внешним модулем, разработанным на C.

Я также пробовал с GDb, как предлагает @GrahamDumpleton, и это результат, не очень полезный :(

Отладчик запускается, и когда я нажимаю на ссылку, которая вызывает модуль c, он снова падает с ошибкой сегментации.

(gdb) run -X
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /usr/local/sbin/httpd -X
[New LWP 101064]
[New Thread 28501140 (LWP 101064)]


Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 28501140 (LWP 101064)]
0x2847d423 in fwrite () from /lib/libc.so.7

Что ж, после ошибки сегментации я попытался использовать команду «где» в отладчике, и вот что она дает:

(gdb) where
#0  0x2847d423 in fwrite () from /lib/libc.so.7
#1  0x293f8d09 in generar () from /ruta/al/codigo/generador.so
#2  0x28912caa in PyCFunction_Call () from /usr/local/lib/libpython2.7.so
#3  0x2896e49a in PyEval_EvalFrameEx () from /usr/local/lib/libpython2.7.so
#4  0x2897044b in PyEval_EvalCodeEx () from /usr/local/lib/libpython2.7.so
#5  0x288feafd in PyClassMethod_New () from /usr/local/lib/libpython2.7.so
#6  0x288d622c in PyObject_Call () from /usr/local/lib/libpython2.7.so
#7  0x2896c27a in PyEval_EvalFrameEx () from /usr/local/lib/libpython2.7.so
#8  0x2896fadc in PyEval_EvalFrameEx () from /usr/local/lib/libpython2.7.so
#9  0x2897044b in PyEval_EvalCodeEx () from /usr/local/lib/libpython2.7.so
#10 0x288fea0a in PyClassMethod_New () from /usr/local/lib/libpython2.7.so
#11 0x288d622c in PyObject_Call () from /usr/local/lib/libpython2.7.so
#12 0x288e4fd8 in PyClass_IsSubclass () from /usr/local/lib/libpython2.7.so
#13 0x288d622c in PyObject_Call () from /usr/local/lib/libpython2.7.so
#14 0x2893044c in _PyObject_LookupSpecial () from /usr/local/lib/libpython2.7.so
#15 0x288d622c in PyObject_Call () from /usr/local/lib/libpython2.7.so
#16 0x28968ec4 in PyEval_CallObjectWithKeywords () from /usr/local/lib/libpython2.7.so
#17 0x2889b229 in Adapter_run (self=0x28b4dd58, object=0x28c7d50c) at mod_wsgi.c:3841
#18 0x2889be50 in wsgi_execute_script (r=0x28cb4058) at mod_wsgi.c:6547
#19 0x2889de66 in wsgi_hook_handler (r=0x28cb4058) at mod_wsgi.c:9080
#20 0x08076b19 in ap_run_handler (r=0x28cb4058) at config.c:157
#21 0x08079dee in ap_invoke_handler (r=0x28cb4058) at config.c:376
#22 0x08084eb0 in ap_process_request (r=0x28cb4058) at http_request.c:282
#23 0x0808201b in ap_process_http_connection (c=0x28b201f0) at http_core.c:190
#24 0x0807de09 in ap_run_process_connection (c=0x28b201f0) at connection.c:43
#25 0x08089791 in child_main (child_num_arg=Variable "child_num_arg" is not available.
) at prefork.c:662
#26 0x080899e3 in make_child (s=0x28510f10, slot=0) at prefork.c:707
#27 0x0808a591 in ap_mpm_run (_pconf=0x2850f018, plog=0x2853d018, s=0x28510f10) at  prefork.c:983
#28 0x08064195 in main (argc=676384792, argv=0x28b1e018) at main.c:739

person Pedro Muñoz    schedule 27.07.2011    source источник
comment
Не публикуйте один и тот же вопрос дважды под двумя разными (хотя и похожими) именами пользователей. Просто используйте один. Ваш другой вопрос лучше задать и отформатировать по адресу stackoverflow.com/questions/6840682/.   -  person agf    schedule 27.07.2011
comment
Можете ли вы опубликовать код? Без него segfault практически невозможно диагностировать.   -  person Morgan Harris    schedule 27.07.2011
comment
@agf, это, наверное, мой брат, мы вместе работаем над этим проектом   -  person Pedro Muñoz    schedule 27.07.2011
comment
И вы оба разместили один и тот же вопрос в одно и то же время на одном и том же сайте случайно?   -  person agf    schedule 27.07.2011
comment
@agf, нет, мы говорили об этом и сказали, что можем спросить в stackoverflow. Я пишу этот вопрос (кстати, мой первый вопрос), и он также пишет еще один перед сном (уже больше 3 часов ночи).   -  person Pedro Muñoz    schedule 27.07.2011
comment
@MorganHarris Я отправил код, также нужен код c?   -  person Pedro Muñoz    schedule 27.07.2011
comment
Когда ошибка возникает в gdb, вы должны запустить команду «где» или «поток применить все bt», чтобы получить трассировку стека. Вам все еще нужно сказать отладчику, что вы хотите, когда он выйдет из строя. Если вы собираетесь писать расширения на C, вам действительно нужно научиться правильно использовать отладчик.   -  person Graham Dumpleton    schedule 27.07.2011
comment
Попробуйте перестроить свой модуль расширения с символами отладки в нем. Смотрите обновление к моему ответу ниже о том, как это сделать. Затем вы можете использовать gdb, чтобы узнать, какие переменные установлены, и выяснить, что происходит.   -  person Graham Dumpleton    schedule 27.07.2011


Ответы (1)


Попробуйте установить:

WSGIApplicationGroup %{GLOBAL}

и заставить приложение работать в основном интерпретаторе Python.

Возможно, ваше расширение C не написано должным образом для работы с интерпретаторами Python.

Видеть:

http://code.google.com/p/modwsgi/wiki/ApplicationIssues#Python_Simplified_GIL_State_API

Ваш код также может быть просто ошибочным, и его использование под mod_wsgi показывает проблему, в которой работает командная строка Python.

Видеть:

http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Debugging_Crashes_With_GDB

о том, как отлаживать место, где происходит сбой.


ОБНОВЛЕНИЕ 1

При сборке модуля расширения, чтобы облегчить отладку в gdb, убедитесь, что оптимизация не включена при компиляции модуля расширения, а параметры отладки включены.

Для сборки модуля расширения, управляемого setup.py, я считаю необходимым добавить:

from distutils import sysconfig
dummy = sysconfig.get_config_vars('CFLAGS', 'OPT')
config_vars = sysconfig._config_vars
config_vars['CFLAGS'] = config_vars['CFLAGS'].replace(' -Os ', ' ')
config_vars['OPT'] = config_vars['OPT'].replace(' -Os ', ' ')

Таким образом можно избавиться от опций -Os. Будет ли это -Os или -O, зависит от вашей установки Python.

Затем проверьте -g в параметрах компилятора при построении модуля расширения и добавьте его, если это необходимо.

Как только это будет сделано, вы можете использовать gdb для фактического вывода значений переменных, получения фактических номеров строк и т. д.

person Graham Dumpleton    schedule 27.07.2011
comment
Спасибо! Я пытаюсь с WSGIApplicationGroup %{GLOBAL}, но система снова дает сбой, текущая отладка с помощью GDB, если у вас есть дополнительные ссылки на API для расширения Python с помощью C и распространенных ошибок, это будет здорово! - person Pedro Muñoz; 27.07.2011
comment
Как вы должны знать, есть и сама документация по Python. В частности, о расширении и встраивании, а также Python/C API. python.org/doc - person Graham Dumpleton; 27.07.2011
comment
Хорошо, спасибо, в начале мы не думали о написании расширения C, но для производительности мы попробовали его после того, как начали обрабатывать миллионы регистров, и процесс стал очень медленным. - person Pedro Muñoz; 27.07.2011
comment
Что ж, эта проблема решена, были некоторые проблемы, такие как указатели C, которые приводили к сбою приложения, и мы добавили EnableSendfile в httpd.conf, спасибо! - person Pedro Muñoz; 28.07.2011
comment
Если ваш код содержит ошибки, установка для параметра «EnableSendfile» значения «on» или изменение того, что для него установлено, не должно иметь значения. Изменение настройки может устранить проблему, но внесите некоторые другие изменения, и она, скорее всего, вернется. Итак, какая связь? - person Graham Dumpleton; 28.07.2011