python: функции из модулей math и os прерываются EINTR
У меня есть плата Linux на Samsung SoC S3C6410 (ARM11). Я собираю rootfs с помощью buildroot: Python 2.7.1, uClibc-0.9.31. Ядро Linux: Linux buildroot 2.6.28.6 #177 Пн, 3 октября 12:50:57 EEST 2011 armv6l GNU/Linux
Мое приложение, написанное на python, в некоторых условиях mysterios вызывает следующие исключения:
1) исключение:
File "./dfbUtils.py", line 3209, in setItemData
ValueError: (4, 'Interrupted system call')
код:
currentPage=int(math.floor(float(rowId)/self.pageSize))==self.selectedPage
2) исключение:
File "./terminalGlobals.py", line 943, in getFirmawareName
OSError: [Errno 4] Interrupted system call: 'firmware'
код:
for fileName in os.listdir('firmware'):
Немного информации о приложении: оно имеет 3-7 потоков, слушает последовательные порты через модуль 'serial', использует графический интерфейс, реализованный через расширение c, которое оборачивает directfb, я не могу воспроизвести эти исключения, они не предсказуемы.
Я гуглил исключения EINTR в python, но обнаружил, что EINTR может происходить только при медленных системных вызовах и сокете, подпроцессе модулей python, а другой уже является процессом EINTR. Так что же происходит в моем приложении? Почему простой вызов математической функции может прервать программу в любое время, это совсем не надежно. У меня есть только предложения: ошибка ulibc, ошибка обработки ядра /hw. Но эти предложения не показывают мне решение.
Теперь я создал функции обтекания (которые перезапускают работу в случае EINTR) вокруг некоторых функций из модуля os, но обтекание математического модуля увеличит время выполнения в 2 раза. Есть еще один вопрос: если математика может быть нарушена, чем другой модуль также может и как получить надежность?
PS Я понимаю, что библиотечный вызов (например, в libm) не системный вызов, так почему у меня "Прерванный системный вызов"?
1 ответ
Был старый баг с потоками и EINTR
в uClibc (#4994), который они исправили в 0.9.30. Исправление было протестировано на pthreads, поэтому я хотел бы предложить предложение от tMC, чтобы проверить, как вы настраивали потоки при сборке uClibc.
Также вы можете попробовать компилировать с опцией malloc-simple? Это медленно, но если ваша проблема исчезнет, это также может означать проблемы с потоками:
malloc-simple
тривиально прост и медлен, как патока. Он был написан с нуля для uClibc и является самой простой (и поэтому самой маленькой) реализацией malloc.Это использует только
mmap()
системный вызов, чтобы выделить и освободить память, и не используетbrk()
системный вызов вообще, что делает его хорошим выбором для систем без MMU с очень ограниченной памятью. Он на 100% совместим со стандартами, поточно-ориентирован, очень мал и освобождает освобожденную память обратно в ОС, а не хранит ее в куче процесса для перераспределения. Это также очень медленно.