Веб-приложение висит в течение нескольких часов в ssl.py на self._sslobj.do_handshake()
Я использую Python 2.7.5. У меня есть веб-приложение, которое запрашивает API каждые несколько минут и успешно работает в последний день или около того. Однако, оставив его сидеть в течение нескольких часов, я вернулся, чтобы найти, что моя программа застопорилась без каких-либо действий в течение нескольких часов. Я покинул программу и обнаружил, что она была остановлена в методе handshake ssl большую часть дня во время одного из вызовов API.
Вот трассировка:
...
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 143, in __init__
self.do_handshake()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 305, in do_handshake
self._sslobj.do_handshake()
Я провел небольшое исследование, и, похоже, это проблема с библиотеками SSL в Python 2.6, но с тех пор она была исправлена. Мне интересно, почему моя программа застряла здесь, не бросая исключение или что-то еще.
Если есть способ установить тайм-аут для метода установления связи SSL, я с удовольствием сделаю это, так как хотел бы, чтобы моя программа была остановлена на неопределенное время из чего-то подобного. Я использую HTTP-запросы Requests, и это работает на Mac OSX 10.9, если это имеет значение. Предложения?
EDIT:
Я провел некоторое исследование, и похоже, что у других была эта специфическая проблема с SSL, несмотря на "исправление", реализованное в версии 2.6. Однако не уверен, что такое решение. Любая помощь приветствуется.
ИЗМЕНИТЬ 3:
Добавлено мое решение в качестве ответа на этот вопрос.
Ответы
Ответ 1
После просмотра раздела Python я нашел что-то, что может не исправить основную проблему, вызывающую проблему, но, безусловно, достаточно хорошо, чтобы справляться с любой ситуацией, в которой эта проблема возникает. Следующий вопрос имеет различные решения, которые вызывают какое-то исключение, если функция занимает слишком много времени для завершения. Вот как я решил эту проблему в конце. Главный ответ - только UNIX, однако есть и другие, которые используют потоки и работают на каждой платформе:
Функция тайм-аута, если требуется слишком много времени для завершения
Это странная проблема, которую очень трудно воспроизвести. Я видел это только два раза после тысяч и тысяч вызовов API. Я думаю, что маловероятно, что кто-то придет к лучшему решению, чем этот, это своего рода взлом, но определенно решает проблему. Вы можете выбросить исключение, затем либо снова попытаться подключиться к SSL, либо продолжить работу с другой частью вашей программы.
Я думаю, что на данный момент мой ответ будет достаточным, но если у кого-то есть что-то лучше, не стесняйтесь предлагать его вперед. Честно говоря, похоже, что единственным исправлением основной проблемы может быть исправление ошибок в фактической библиотеке ssl.py, но я не могу сказать точно.
Ответ 2
Я столкнулся с этим и смог обойти его, используя socket.setdefaulttimeout. socket.setdefaulttimeout
изменяет поведение всех сокетов, созданных после его вызова, что удобно, если сокет инкапсулирован в код библиотеки. Если у вас есть доступ к определенному SSL-сокету, вы можете использовать socket.settimeout
.