Веб-приложение висит в течение нескольких часов в 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.