“BlockingIOError: [Errno 11] Resource temporarily unavailable” pour Python 3.6


La toute première version de Python 3.6 avait un bug assez vicieux qui ne se manifestait que sous certaines conditions, généralement dans un daemon sur un serveur, et en important certains modules qui finissent par déclencher par réaction en chaîne l’usage de random.

django est concerné.

On tombait dessus généralement assez tard, à la mise en prod, avec un message cryptique:

 
BlockingIOError: [Errno 11] Resource temporarily unavailable 
  
 The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
   .... <- des imports de votre code qui ne font rien de mal
   File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 36, in  
     import email.parser 
   File "/usr/local/lib/python3.6/email/parser.py", line 12, in  
     from email.feedparser import FeedParser, BytesFeedParser 
   File "/usr/local/lib/python3.6/email/feedparser.py", line 27, in  
     from email._policybase import compat32 
   File "/usr/local/lib/python3.6/email/_policybase.py", line 9, in  
     from email.utils import _has_surrogates 
   File "/usr/local/lib/python3.6/email/utils.py", line 28, in  
     import random 
   File "/usr/local/lib/python3.6/random.py", line 742, in  
     _inst = Random() 
 SystemError:  returned a result with an error set 

Cela a été corrigé rapidement, et le binaire patché ajoute juste un “+” à sa version:

$ python --version
Python 3.6.0+

En théorie vous ne pouvez pas tomber dessus, tous les liens de téléchargement ont été mis à jour, les distributions ont changé leurs dépôts, etc.

Mais hier je me suis fait bien niqué, et j’ai perdu 1h à debugguer cette surprise qui n’avait aucun sens (puisque mon code allait bien) : les bugs dans les binaires officiels sont rares et c’est le dernier endroit où je cherche.

En effet, certaines sources non-officielles pour installer Python n’ont pas été mises à jour, et c’est le cas du très populaire PPA deadsnakes.

Si vous avez installé Python 3.6 en faisant :

sudo add-apt-repository ppa:fkrull/deadsnakes
sudo apt-get update
sudo apt-get install python3.6

vous l’avez dans le cul.

Il existe un PPA plus à jour si vous avez besoin de corriger le tir :

sudo add-apt-repository ppa:jonathonf/python-3.6
sudo apt-get update
sudo apt-get install python3.6

Donc si vous avez compilé Python à la main ou utilisé un PPA, assurez-vous bien d’avoir la bonne version, et sinon upgradez. En attendant j’ai un bug report à faire à deadsnakes

6 thoughts on ““BlockingIOError: [Errno 11] Resource temporarily unavailable” pour Python 3.6

  • haypo

    C’est le bug http://bugs.python.org/issue29085 : régression de Python 3.6.0 connue et corrigée par https://github.com/python/cpython/commit/acc2f74ca991f6579f5b9055dfe885b9a8af4645 … sauf que Python 3.6.1 n’est prévu que pour le 2017-03-13 :-( Je n’ai jamais compris pourquoi les releases managers attendent 3 mois après une version x.y.0 qui ajoute des milliers de changements et donc leur lot de régression. Bref, c’est résolu dans qq. jours.

    Le bug est que tu lances une application Python sur une système où le générateur de nombres aléatoires de Linux n’est pas encore entièrement initialisé. C’est censé prendre quelques secondes au boot, mais sur des VM mal configurée (hé oui), ça peut prendre de longues minutes… Voir https://haypo.github.io/pep-524-os-urandom-blocking.html qui explique la raison du changement (c’est moi qui ait ajouté le bug dans le module random, désolé !).

    Contournement pas sûr (je ne suis pas sûr que le RNG HAVEGE soit 100% sûr dans une VM) mais efficace : installer haveged pour “corriger” la VM, injecte de l’entropie selon le “bruit” du CPU. Si tu héberges toi même tes VM, ajouter le pilote virtio-rng et là c’est nickel.

    Contournement en Python : lance “python3.6 -S -c ‘import os; os.urandom(1)’ ” avant ton application, la commande bloque jusqu’à ce le RNG soit entièrement initialisé.

    Allez, faut se dire que c’est augmenter la sécurité de Python qu’on s’est payé ce bug ;-)

  • Sam Post author

    Ouai quand j’ai vu la stack trace, je me suis souvenu qu’un certain victor avait touché à random, et je t’ai bien maudi. Mais bon, j’ai fais bien pire comme connerie dans ma vie :)

  • Marc

    Existe-t-il un bout de code ou autre permettant de constater que nous sommes confronté au problème sur nos environnements ?

  • haypo

    @Marc: Bah si t’as Python 3.6.0, t’as une version qui a le bug. Après pour reproduire le bug, il faut se lever de bonne heure car c’est un très limite qui ne produit que sous certaines conditions. Lit la PEP 524 pour voir. L’autre contournement est d’utiliser Python 3.5 hein :-)

  • blackmoor

    Petite typo: au début –> “certains modules qui finissent pas déclencher par réaction” –> par déclencher

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.