2009-04-29 8 views
7

Y a-t-il un moyen d'intégrer python, d'autoriser les callbacks de python vers C++, en permettant au code Python de générer des threads, et d'éviter les blocages?Intégration de Python avec des threads - évitant les blocages?

Le problème est le suivant:

  • Pour appeler en Python, je dois tenir le GIL. Généralement, je le fais en obtenant l'état du thread principal lorsque je crée l'interpréteur, puis en utilisant PyEval_RestoreThread() pour prendre le GIL et permuter l'état du thread avant d'appeler Python. En cas d'appel de Python, il se peut que j'aie besoin d'accéder à certaines ressources protégées qui sont protégées par une section critique distincte dans mon hôte. Cela signifie que Python tiendra le GIL (potentiellement à partir d'un autre thread que j'ai appelé initialement), puis tenter d'acquérir mon verrou de protection. Lorsque j'appelle en Python, il se peut que je doive avoir les mêmes verrous, car il se peut que je fasse une itération sur une collection d'objets, par exemple.

Le problème est que même si je tiens le GIL quand je l'appelle en Python, Python peut donner, donnez à un autre fil, et alors que l'appel de fil dans mon hôte, attendant de prendre l'hôte serrures. Pendant ce temps, l'hôte peut prendre les verrous de l'hôte, et le verrou GIL, et appeler en Python. L'impasse s'ensuit.

Le problème ici est que Python abandonne le GIL à un autre thread pendant que je l'ai appelé. C'est ce que l'on s'attend à faire, mais il est impossible de séquencer le verrouillage - même si je prends d'abord GIL, puis je prends mon propre verrou, puis j'appelle Python, Python va appeler mon système depuis un autre thread, m'attendant à prendre mon propre verrou (parce qu'il a déséquilibré le GIL en le libérant).

Je ne peux pas vraiment faire en sorte que le reste de mon système utilise le GIL pour tous les verrous possibles dans le système - et cela ne fonctionnerait même pas correctement, car Python peut encore le libérer sur un autre thread.

Je ne peux pas vraiment garantir que mon hôte ne détienne pas de verrous en entrant dans Python, car je ne contrôle pas tout le code de l'hôte.

Alors, est-ce que c'est juste que ça ne peut pas être fait?

+0

Pourriez-vous demander à votre code C++ de contenir le GIL avant qu'il n'acquiert les verrous de l'hôte? – Dave

Répondre

2

"Lors de l'appel en Python, il se peut que je doive avoir les mêmes verrous, car il se peut que je fasse une itération sur une collection d'objets, par exemple."

Ceci indique souvent qu'un seul processus avec plusieurs threads n'est pas approprié. C'est peut-être une situation où plusieurs processus - chacun avec un objet spécifique de la collection - ont plus de sens.

Processus indépendant - chacun avec son propre pool de threads - peut être plus facile à gérer.

+0

Un seul processus est exactement ce dont j'ai besoin (le processus en question est en fait un plug-in de navigateur Web). Ainsi, malheureusement, votre suggestion ne répond pas ou ne s'applique pas à ma question. –

+1

S'il vous plaît mettre à jour votre question avec des faits supplémentaires - ne pas ajouter d'informations dans les commentaires. Le "plug-in du navigateur Web" est une information nouvelle et appartient à la question. –

2

Le code appelé par python doit libérer le GIL avant de prendre l'un de vos verrous. De cette façon, je crois qu'il ne peut pas entrer dans le dead-lock.

+0

Bonne réponse. Rappelez-vous que le GIL existe uniquement pour protéger les structures de données internes de l'interpréteur Python. Si un thread appelle un code non-Python, il peut libérer le GIL en toute sécurité pendant l'exécution de ce code. – mhsmith

-1

Il y a eu récemment une discussion sur un problème similaire sur la liste de pyopenssl. J'ai peur que si j'essaie d'expliquer cela, je vais me tromper, donc je vous renvoie à the problem in question.

Questions connexes