Ошибка сегментации в приложении Python uWSGI
Я довольно новичок в использовании uwsgi со скриптами Python, так что, надеюсь, это наивная ошибка.
У меня есть два разных веб-приложения, которые взаимодействуют с отдельными, но связанными библиотеками Python, давайте назовем их lib1.py и lib2.py
Если я использую эти библиотеки из командной строки, я не получаю ошибок.
Я создал два файла Python, app1.py и app2.py, каждый из которых подключен к разным сокетам uwsgi. Базовая структура этих файлов:
import lib1.py
#load objects into memory
MyObject = lib1.MyClass(init_params)
application(environ, start_response):
status = '200 OK'
output = MyObject.processRequest()
response_headers = [('Content-type', 'text/html'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
То же самое для app2.py, импортирующего lib2...
App1 прекрасно работает, и у меня не было проблем с его настройкой. Он загружает десятки больших (100000+ строк, ~100 столбцов) массивов при инициализации MyObject и сохраняет их в памяти для функции приложения, чтобы рассчитать, когда он получает запросы от веб-сервера.
App2 еще не работает... lib2.py импортирует lib1.py, так как ему необходимо выполнять аналогичные вычисления для большого массива с массивами в рамках своей работы. Странно то, что это одна из функций lib1.py, которая выдает SEGFAULT. Сначала я подумал, что, может быть, это был какой-то странный случай двойного импорта, поэтому я разделил uwsgi на два отдельных сокета и приложения, как описано выше, когда впервые увидел это. Более странно то, что lib2 использует только 1 большой массив numpy, и он меньше, чем самый большой из массивов lib1. Размещая ряд print
Заявления в мой код и просматривая журналы, я смог найти точную строку, где происходит segfault:
inner_product_array = np.dot(self.coordinates, vector.T)
self.coordinates - это двумерный массив MxN, а vector.T - вектор-столбец Nx1. SEGFAULT исчезнет, если я ограничу массив self.coordinates следующим образом: self.coordinates[:500,:]
Но SEGFAULT происходит всякий раз, когда ломтик становится намного больше, чем 500, что далеко не так, как мне нужно 150000. Опять же, этот расчет не вызывает проблем в lib1, когда self.coordinates может получить до 500000 x 200
Я чувствую, что выполнил как можно больше, чтобы убедиться, что ни один модуль / библиотека не был дважды импортирован. Другие функции numpy ведут себя нормально, и, опять же, lib2 прекрасно работает с большими массивами при использовании из командной строки.
Единственный другой странный признак, который стоит упомянуть, это то, что раньше, когда у меня был один файл app.py, который обрабатывал весь мой код Python uwsgi и обрабатывал запросы для разных приложений, используя переменную среды PATH_INFO (включая другие, кроме этих двух), все приложения хорошо работали вместе, пока я не добавил lib2. Как только lib2 был добавлен, lib1 сломался и начал давать SEGFAULTS. Другие приложения (которые не зависят от lib1 или lib2) были в порядке.
Вот ошибка из журнала:
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 33866, cores: 1)
!!! uWSGI process 33866 got Segmentation Fault !!!
*** backtrace of 33866 ***
0 uwsgi 0x00000001062f9420 uwsgi_backtrace + 48
1 uwsgi 0x00000001062f9963 uwsgi_segfault + 51
2 libsystem_platform.dylib 0x00007fff9190ef1a _sigtramp + 26
3 multiarray.so 0x0000000106fd4efe array_dealloc + 158
4 libBLAS.dylib 0x00007fff908911ff rowMajorNoTranspose + 689
5 libBLAS.dylib 0x00007fff9088f2c9 cblas_dgemv + 783
6 _dotblas.so 0x00000001072e0129 dotblas_matrixproduct + 5513
7 libpython2.7.dylib 0x00000001067d27c9 PyEval_EvalFrameEx + 14387
8 libpython2.7.dylib 0x00000001067ced62 PyEval_EvalCodeEx + 1413
9 libpython2.7.dylib 0x00000001067d557d _PyEval_SliceIndex + 757
10 libpython2.7.dylib 0x00000001067d23e3 PyEval_EvalFrameEx + 13389
11 libpython2.7.dylib 0x00000001067ced62 PyEval_EvalCodeEx + 1413
12 libpython2.7.dylib 0x00000001067d557d _PyEval_SliceIndex + 757
13 libpython2.7.dylib 0x00000001067d23e3 PyEval_EvalFrameEx + 13389
14 libpython2.7.dylib 0x00000001067ced62 PyEval_EvalCodeEx + 1413
15 libpython2.7.dylib 0x00000001067d557d _PyEval_SliceIndex + 757
16 libpython2.7.dylib 0x00000001067d23e3 PyEval_EvalFrameEx + 13389
17 libpython2.7.dylib 0x00000001067ced62 PyEval_EvalCodeEx + 1413
18 libpython2.7.dylib 0x00000001067d557d _PyEval_SliceIndex + 757
19 libpython2.7.dylib 0x00000001067d23e3 PyEval_EvalFrameEx + 13389
20 libpython2.7.dylib 0x00000001067ced62 PyEval_EvalCodeEx + 1413
21 libpython2.7.dylib 0x000000010677330a PyFunction_SetClosure + 826
22 libpython2.7.dylib 0x00000001067552ac PyObject_Call + 99
23 libpython2.7.dylib 0x00000001067d4d6b PyEval_CallObjectWithKeywords + 93
24 uwsgi 0x0000000106314097 python_call + 23
25 uwsgi 0x000000010631620f uwsgi_request_wsgi + 879
26 uwsgi 0x00000001062ab530 wsgi_req_recv + 288
27 uwsgi 0x00000001062f7205 simple_loop_run + 229
28 uwsgi 0x00000001062fe577 uwsgi_ignition + 439
29 uwsgi 0x00000001062fe363 uwsgi_worker_run + 835
30 uwsgi 0x00000001062fbe7a uwsgi_run + 442
31 uwsgi 0x00000001062f9b0e main + 14
32 libdyld.dylib 0x00007fff854425c9 start + 1
*** end of backtrace ***
И вот конфиг xml для uwsgi, который я использую для app2:
<uwsgi>
<socket>127.0.0.1:3033</socket>
<chdir>/abs/path/to/site_folder/wsgi</chdir>
<wsgi-file>/abs/path/to/site_folder/wsgi/app2.py</wsgi-file>
<logto>/abs/path/to/logdir/app2.log</logto>
<pidfile>app2.pid</pidfile>
<enable-threads></enable-threads>
<daemonize2></daemonize2>
</uwsgi>
ОБНОВИТЬ
Я создал идентичную настройку на сервере Amazon Linux EC-2, и все работало без ошибок. Локальная машина, на которой у меня возникла проблема - это OSX. Я все еще не понимаю, почему это происходит только в среде uWSGI, и хотел бы иметь возможность разрабатывать и тестировать локально, но, похоже, это скорее проблема установки (OpenBLAS?), Чем что-либо еще. Любые идеи, почему uWSGI будет вызывать это неправильное поведение на идентичных данных и при идентичном вызове функции как сценарий командной строки без ошибок и отдельное приложение uWSGI без ошибок?