Сбой Python из-за сбоя libdispatch дочернего потока - PullRequest
0 голосов
/ 21 марта 2019

Я использую библиотеку pynetdicom для получения и обработки медицинских изображений dicom. Обработка выполняется в функции обратного вызова "on_association_released". Тем не менее, при получении определенных исследований, это приведет к сбою Python из-за того, что кажется, что происходит сбой дочернего потока.

Из отчета о сбое OSX кажется, что это библиотека libdispatch, которая является причиной, но не уверена, как и почему.

Это функция:

def on_association_released(self):

    if not self.auto_process:
        self.incoming = []
        return

    dicoms = [Dicom(f=x) for x in self.incoming]
    self.incoming = []
    incoming = Study(dicom_list=dicoms)
    log.info("Incoming study: {incoming}".format(**locals()))
    completed_tasks = {}
    time.sleep(1)
    for task in AVAILABLE_PROCESS_TASKS:

        log.info("Trying task: {task}".format(**locals()))
        process_task = task(study=incoming)

        try:
            if process_task.valid:

                log.info("{incoming} is valid for {process_task}".format(**locals()))
                try:
                    process_task.process()

                except Exception as e:
                    log.warning(
                        'Failed to perform {process_task} on {incoming}: \n {e}'.format(**locals())
                    )

                else:
                    log.info("Completed {process_task} for {incoming} !".format(**locals()))
            else:
                log.warning("{incoming} is not a valid study for {process_task}".format(**locals()))

        except Exception as e:

            log.warning("{incoming} could not be assessed by {process_task}".format(**locals()))

            myemail.nhs_mail(recipients=[admin],
                             subject=f"dicomserver {VERSION}: Failed to start listener",
                             message=f"{incoming} could not be assessed by {process_task}: {e.args}"
                             )

Это последнее сообщение в журнале приложения:

2019-03-15 12:19:06 I [process.py:on_association_released:171] Incoming study: Study(1.2.826.0.1.2112370.55.1.12145941)

Это отчет о сбое OSX:

Process:               Python [84177]
Path:                  /Library/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python
Identifier:            Python
Version:               3.6.1 (3.6.1)
Code Type:             X86-64 (Native)
Parent Process:        Python [84175]
Responsible:           Terminal [346]
User ID:               503

Date/Time:             2019-03-15 12:19:06.371 +0000
OS Version:            Mac OS X 10.11.6 (15G1108)
Report Version:        11
Anonymous UUID:        E7340644-9523-1C6B-0B2B-74D6043CFED6


Time Awake Since Boot: 590000 seconds

System Integrity Protection: enabled

Crashed Thread:        1

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000110

VM Regions Near 0x110:
--> 
    __TEXT                 0000000100000000-0000000100001000 [    4K] r-x/rwx SM=COW  /Library/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python

Application Specific Information:
*** multi-threaded process forked ***
crashed on child side of fork pre-exec

Это вершина трассировки аварийного завершения потока 1:

        Thread 1 Crashed:
    0   libdispatch.dylib               0x00007fff8e6cc661 _dispatch_queue_push_queue + 345
    1   libdispatch.dylib               0x00007fff8e6cab06 _dispatch_queue_wakeup_with_qos_slow + 126
    2   libdispatch.dylib               0x00007fff8e6d113f _dispatch_mach_msg_send + 1952
    3   libdispatch.dylib               0x00007fff8e6d08dc dispatch_mach_send + 262
    4   libxpc.dylib                    0x00007fff86858fc9 xpc_connection_send_message_with_reply + 131
    5   com.apple.CoreFoundation        0x00007fff8ef43b3f __66-[CFPrefsSearchListSource generationCountFromListOfSources:count:]_block_invoke_2 + 143
    6   com.apple.CoreFoundation        0x00007fff8ef4396d _CFPrefsWithDaemonConnection + 381
    7   com.apple.CoreFoundation        0x00007fff8ef42af6 __66-[CFPrefsSearchListSource generationCountFromListOfSources:count:]_block_invoke + 150
    8   com.apple.CoreFoundation        0x00007fff8ef42893 -[CFPrefsSearchListSource generationCountFromListOfSources:count:] + 179
    9   com.apple.CoreFoundation        0x00007fff8ef42174 -[CFPrefsSearchListSource alreadylocked_copyDictionary] + 324
    10  com.apple.CoreFoundation        0x00007fff8ef41dbc -[CFPrefsSearchListSource alreadylocked_copyValueForKey:] + 60
    11  com.apple.CoreFoundation        0x00007fff8ef41d4c ___CFPreferencesCopyAppValueWithContainer_block_invoke + 60
    12  com.apple.CoreFoundation        0x00007fff8ef39a70 +[CFPrefsSearchListSource withSearchListForIdentifier:container:perform:] + 608
    13  com.apple.CoreFoundation        0x00007fff8ef397c7 _CFPreferencesCopyAppValueWithContainer + 183
    14  com.apple.SystemConfiguration   0x00007fff998b3a9b SCDynamicStoreCopyProxiesWithOptions + 163
    15  _scproxy.cpython-36m-darwin.so  0x000000010f0f5a63 get_proxy_settings + 35
    16  org.python.python               0x000000010006a604 _PyCFunction_FastCallDict + 436
    17  org.python.python               0x00000001000f33e4 call_function + 612
    18  org.python.python               0x00000001000f8d84 _PyEval_EvalFrameDefault + 21892

1 Ответ

3 голосов
/ 21 марта 2019

Эта проблема выглядит очень похоже на давнюю проблему с Python на MacOS.

Насколько я понимаю, коренная причина в том, что fork() трудно сделать правильно, если в нем задействованы потоки, если только вы не exec().

MacOS снова «защищает» возможные ловушки, сбивая процесс, если он обращается к определенным системным функциям, таким как libdispatch, если он fork редактировал, но еще не exec.

К сожалению, эти вызовы могут происходить в неожиданных местах, например, в _scproxy.cpython-36m-darwin.so, который показан в позиции 15 трассировки стека.

Об этом подано несколько ошибок Python (например, 1 , 2 , 3 ), но серебряной пули, насколько я знаю.

В вашем конкретном случае может быть возможным для предотвращения сбоя, запустив ваш интерпретатор Python с переменной окружения no_proxy=*. Это должно предотвратить вызовы в конфигурацию системы scproxy для поиска параметров прокси.

...