我对使用uwsgi和python脚本相当新,所以希望这是一个天真的错误。
我有两个不同的Web应用程序与单独但相关的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效果很好,我设置它没有问题。当MyObject初始化时,它会加载数十个大的(100000多行,~100列)numpy数组,并将它们保存在内存中,以便应用程序函数在接收来自Web服务器的请求时进行计算。
App2尚未运行... lib2.py导入lib1.py,因为它需要在大型numpy数组上进行类似的计算,作为其工作的一部分。奇怪的是它是一个抛出SEGFAULT的lib1.py函数。起初,我认为这可能是一些奇怪的双重导入的症状,这就是为什么我在第一次看到这种情况时将uwsgi分成两个独立的套接字和应用程序,如上所述。更奇怪的是,lib2只使用了1个大的numpy数组,并且它比lib1 numpy数组中的最大数组小。通过在我的代码中放置一些print
语句并查看日志,我能够找到发生段错误的确切行:
inner_product_array = np.dot(self.coordinates, vector.T)
self.coordinates是2d MxN数组,vector.T是Nx1列向量。如果我限制self.coordinates数组,那么SEGFAULT就会消失:self.coordinates[:500,:]
但只要切片大于500,就会发生SEGFAULT,这远远超过我需要的150000。同样,当self.coordinate可以达到500000 x 200
时,这个计算在lib1中没有问题我觉得我已经尽可能地确保没有模块/库被双重导入。其他numpy函数表现良好,并且,当从命令行使用时,lib2再次适用于大型数组。
唯一需要提及的另一个奇怪的症状是,之前,当我有一个app.py文件处理我所有的uwsgi python代码并使用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 ***
这是我用于app2的uwsgi的xml配置:
<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应用程序?