Вопрос

Я сделал расширение AC из сценария Python, который был довольно трудоемким. Сам код хорошо протестирован и простой. Расширение C вызывается с несколькими большими списками, а затем выполняет некоторую умную арифметику и возвращает несколько новых списков. Расширение C на 100% самодостаточное, он не использует никакие другие функции C и не использует какие -либо из методов объектов Python (он использует эти стандартные методы Python, однако: Pyfloat_asdouble, pylist_getitem, pylist_size, pylist_new, py_buildvalue, pylist_append, pylist_new, py_buildvalu ) До сих пор я использовал его только в не-мультичковой среде.

Сегодня я начал использовать его в многопоточной среде GUI, и весь ад сломался. У меня есть несколько тестовых примеров, которые я использую для отладки, и достаточно странно, что меньшие проходят через OK, в то время как более крупные приводят к ошибкам шины и ошибки сегментации (полностью сбоя графического интерфейса и поднимая «отчет о проблеме для окна Python» в OS X) Анкет Проблема, что мое расширение C не Threadsafe? Если так, как я могу сделать это Threadsafe? Я попробовал поиск предмета, но я не нашел никакой хорошей информации, которую я могу понять. Я проверил это а также это Пейги, но я не очень понимаю, что они говорят. Какой тип кода понадобится GIL, а какой нет?

За то, что здесь стоит свалка:

Date/Time:       2010-10-23 03:48:02.714 +0800
OS Version:      Mac OS X 10.6.4 (10F569)
Report Version:  6

Interval Since Last Report:          323080 sec
Crashes Since Last Report:           60
Per-App Interval Since Last Report:  110157 sec
Per-App Crashes Since Last Report:   59
Anonymous UUID:                      5BD8D75B-9B21-4267-98A4-BAA31E56CB5C

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000b009286c
Crashed Thread:  2

Thread 0:  Dispatch queue: com.apple.main-thread
0   ...ple.CoreServices.CarbonCore  0x90b024c8 ConvertFromUnicodeToTextImplementation + 1976
1   com.apple.HIToolbox             0x951c99e5 CEncodingTranslator::TranslateFromUnicode(char*, unsigned long, unsigned long*, unsigned long*, unsigned long*, unsigned long, short, short) + 549
2   com.apple.HIToolbox             0x951c9d01 CEncodingTranslator::Translate(char*, unsigned long, unsigned long*, unsigned long*, unsigned long*, unsigned long, unsigned long, short, short, short*, unsigned long) + 101
3   com.apple.HIToolbox             0x951a9e51 TXNGetDataEncoded + 278
4   libwx_macd-2.8.0.dylib          0x0188c7ee wxMacMLTEControl::GetLastPosition() const + 52
5   libwx_macd-2.8.0.dylib          0x0188bf73 wxTextCtrl::SetInsertionPointEnd() + 21
6   libwx_macd-2.8.0.dylib          0x0188bfc9 wxTextCtrl::AppendText(wxString const&) + 25
7   _controls_.so                   0x1397e357 _wrap_TextCtrl_AppendText + 247 (wxPython.h:48)
8   org.python.python               0x000ca58b PyEval_EvalFrameEx + 21147
9   org.python.python               0x000cc4ba PyEval_EvalCodeEx + 2042
10  org.python.python               0x00041ca2 function_call + 162
11  org.python.python               0x0000f375 PyObject_Call + 85
12  org.python.python               0x000c7d5b PyEval_EvalFrameEx + 10859
13  org.python.python               0x000cc4ba PyEval_EvalCodeEx + 2042
14  org.python.python               0x00041ca2 function_call + 162
15  org.python.python               0x0000f375 PyObject_Call + 85
16  org.python.python               0x000c435e PyEval_CallObjectWithKeywords + 78
17  _core_.so                       0x011859f0 wxPyCallback::EventThunker(wxEvent&) + 234 (helpers.cpp:1759)
18  libwx_macd-2.8.0.dylib          0x0180e360 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) + 108
19  libwx_macd-2.8.0.dylib          0x0180e406 wxEvtHandler::SearchDynamicEventTable(wxEvent&) + 80
20  libwx_macd-2.8.0.dylib          0x0180f205 wxEvtHandler::ProcessEvent(wxEvent&) + 225
21  libwx_macd-2.8.0.dylib          0x0180ef4a wxEvtHandler::ProcessPendingEvents() + 86
22  libwx_macd-2.8.0.dylib          0x0176cd02 wxAppConsole::ProcessPendingEvents() + 102
23  libwx_macd-2.8.0.dylib          0x01806873 wxMacProcessNotifierAndPendingEvents + 33
24  libwx_macd-2.8.0.dylib          0x0183107e wxApp::MacHandleOneEvent(void*) + 90
25  libwx_macd-2.8.0.dylib          0x0183110e wxApp::MacDoOneEvent() + 120
26  libwx_macd-2.8.0.dylib          0x0184b570 wxEventLoop::Dispatch() + 32
27  libwx_macd-2.8.0.dylib          0x01906e71 wxEventLoopManual::Run() + 97
28  libwx_macd-2.8.0.dylib          0x018dd364 wxAppBase::MainLoop() + 76
29  _core_.so                       0x0117c75c wxPyApp::MainLoop() + 52 (helpers.cpp:215)
30  _core_.so                       0x011c9e66 _wrap_PyApp_MainLoop + 82 (_core_wrap.cpp:31686)
31  org.python.python               0x000ca58b PyEval_EvalFrameEx + 21147
32  org.python.python               0x000cc4ba PyEval_EvalCodeEx + 2042
33  org.python.python               0x00041ca2 function_call + 162
34  org.python.python               0x0000f375 PyObject_Call + 85
35  org.python.python               0x00021c66 instancemethod_call + 422
36  org.python.python               0x0000f375 PyObject_Call + 85
37  org.python.python               0x000c8ad6 PyEval_EvalFrameEx + 14310
38  org.python.python               0x000cbc88 PyEval_EvalFrameEx + 27032
39  org.python.python               0x000cc4ba PyEval_EvalCodeEx + 2042
40  org.python.python               0x000cc647 PyEval_EvalCode + 87
41  org.python.python               0x000f0ae8 PyRun_FileExFlags + 168
42  org.python.python               0x000f1a23 PyRun_SimpleFileExFlags + 867
43  org.python.python               0x0010a42b Py_Main + 3163
44  org.python.python               0x00001f82 0x1000 + 3970
45  org.python.python               0x00001ea9 0x1000 + 3753

Thread 1:  Dispatch queue: com.apple.libdispatch-manager
0   libSystem.B.dylib               0x96068942 kevent + 10
1   libSystem.B.dylib               0x9606905c _dispatch_mgr_invoke + 215
2   libSystem.B.dylib               0x96068519 _dispatch_queue_invoke + 163
3   libSystem.B.dylib               0x960682be _dispatch_worker_thread2 + 240
4   libSystem.B.dylib               0x96067d41 _pthread_wqthread + 390
5   libSystem.B.dylib               0x96067b86 start_wqthread + 30

Thread 2 Crashed:
0   ccookies.so                     0x0060a949 my_calc + 249 (ccookies.c:23)
1   org.python.python               0x000ca3e0 PyEval_EvalFrameEx + 20720
2   org.python.python               0x000cbc88 PyEval_EvalFrameEx + 27032
3   org.python.python               0x000cbc88 PyEval_EvalFrameEx + 27032
4   org.python.python               0x000cbc88 PyEval_EvalFrameEx + 27032
5   org.python.python               0x000cc4ba PyEval_EvalCodeEx + 2042
6   org.python.python               0x00041ca2 function_call + 162
7   org.python.python               0x0000f375 PyObject_Call + 85
8   org.python.python               0x00021c66 instancemethod_call + 422
9   org.python.python               0x0000f375 PyObject_Call + 85
10  org.python.python               0x000c435e PyEval_CallObjectWithKeywords + 78
11  org.python.python               0x0010c79c t_bootstrap + 76
12  libSystem.B.dylib               0x9606f81d _pthread_start + 345
13  libSystem.B.dylib               0x9606f6a2 thread_start + 34

Thread 2 crashed with X86 Thread State (32-bit):
  eax: 0x0007d090  ebx: 0x0060a85d  ecx: 0x000ef236  edx: 0xb010f920
  edi: 0x02315180  esi: 0xb0092890  ebp: 0xb018d378  esp: 0xb0092870
   ss: 0x0000001f  efl: 0x00010282  eip: 0x0060a949   cs: 0x00000017
   ds: 0x0000001f   es: 0x0000001f   fs: 0x0000001f   gs: 0x00000037
  cr2: 0xb009286c
Это было полезно?

Решение

Наконец -то мне удалось избавиться от проблемы, но довольно длинным путем. Вот оно.

Я потратил очень очень много времени, пытаясь понять документацию для расширения C и их водораздела. На одной из многочисленных траекторий Google в ту ночь я наткнулся на это Страница, описывающая, как использовать массивы Numpy в расширениях C. Поскольку мои проблемы, казалось, были связаны с производительностью (исходное расширение C работало для небольших наборов данных), я подозревал, что моя реализация зацикливания через списки Python и использование Pylist_getItem для получения данных в их аналоги C не подходил к царапинам. (Я вышел из следующих фактических чисел в расширении C, поскольку он был очень общим C без каких -либо особых вещей.)

Поэтому я решил провести полное переписывание расширения C и моего сценария Python для использования массивов Numpy вместо списков. Это заняло два дня, включая всю отладь. Но теперь это работает как очарование. Все наборы данных обрабатываются ОК, нет никаких признаков ошибок автобусов или недостатков сегментации.

TLDR: используйте массивы Numpy вместо списков Python при работе с большими наборами данных и расширениями Python C, чтобы избежать ошибок шины и ошибок сегментации.

Другие советы

CPYTHON не безопасен по тему. Это цель GIL, которая должна использоваться при доступе или изменении состояния интерпретатора.

Если вам нужны потоки и Python, вам нужно будет использовать реализацию, отличную от CPYTHON (стандартный), такой как Ironpython или Jython, оба из которых совершенно устойчивы в случае резьбы. Есть несколько модифицированных CPYTHON, таких как без стека Python, который также может работать лучше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top