10
votes

Prévenir la boucle infinie Lua

J'utilise des interfaces Lua pour obtenir la prise en charge de Lua dans mon programme C #, le thread du travailleur va geler si l'utilisateur soumet le code comme celui-ci xxx

J'ai un moyen de détecter si une boucle infinie est En cours d'exécution, mais j'ai besoin d'une bonne façon de quitter la méthode de dostring du fil de travail. Des idées?

EDIT: @Kikito, oui je déteigne quelque chose comme ça. Le problème que j'ai est que je ne trouve pas de manière propre de tuer la méthode de dostring, il ressemble à la classe principale des interfaces Lua (LUA) a des dépendances statiques, car si je fais lua.close (); Sur mon exemple, il fera avorter la méthode de dostre, mais la prochaine fois que je parle une classe Lua New Lua (); Il va crancer dire quelque chose sur la mémoire protectrice

EDIT: A Branche de fonctionnalité montrant mon code .Close https://github.com/andersmalmgren/freepie/tree / détecter et récupérer-infite-lua-boucle


5 commentaires

Après 30 secondes de googling, j'ai découvert que Lua soutient les événements de crochet: «Il existe quatre types d'événements pouvant déclencher un crochet: les événements d'appel se produisent à chaque fois que Lua appelle une fonction; Les événements de retour se produisent chaque fois qu'une fonction retourne; Les événements de ligne se produisent lorsque Lua commence à exécuter une nouvelle ligne de code; et les événements comptent après un nombre donné d'instructions ». Voilà. Avec les instances d'interprète, j'ai utilisé une exception dans l'événement «Onsomething» qui est piégé par le fil appelé l'interprète. Je ne sais pas à propos de Lua, cependant.


Quelqu'un a une solution pour les interaces Lua pour C #?


La mise en œuvre de la LUA originale (écrite en C) devrait survivre à un proche (c'est réentrant et l'état est complètement encapsulé). Si le C # on ne veut pas, déposez un bogue. (Vous aurez toujours un certain code dans le crash autrement, par exemple Extrêmement longues (décennies ou plus) Opérations de cordes , les crochets ne vous aideront pas avec cela.)


Désolé pour la réponse tardive, les vacances .. Le C # Wrapper n'est pas un projet très actif: / Mais déposera un problème, merci


J'ai fait une branche de fonctionnalité afin que vous puissiez tester le code ou voir si j'ai fait des erreurs github.com/andersmalmgren/freepie/tree/...


6 Réponses :


0
votes

Je suggère de la manipuler comme une autre erreur Lua. En d'autres termes, menacer le code ci-dessus comme si l'utilisateur venait de écrir

error("Script execution has been cancelled after stalling for too long")


3 commentaires

Eh bien, vous ne pouvez pas le faire de cette façon, car la méthode de dosage est bloquée en faisant la boucle infinie. Je vais mettre à jour mon or orginal avec plus d'informations


Le problème est toujours que je ne trouve pas un moyen d'abandonner l'appel à dosage infini sans casser le moteur Lua pour tous les appels futurs


Je n'ai pas trouvé de moyen d'exécuter le code Lua de l'événement Hook avec le wrapper C #, vous avez trouvé un moyen?



9
votes

Sandboxing Lua

Réglage des crochets n'est pas suffisant du tout pour éviter les déchets inattendus de ressources, sans parler d'abuser - voici un exemple simple (le temps est passé pendant la correspondance de modèle de chaîne, aucun crochet de débogage n'est appelé): < / p>

s = ('a'): REP (20000): Match ('.- B')

Le seul moyen fiable de forcer les contraintes de temps / de mémoire sur une pièce de code LUA consiste à exécuter l'interpréteur LUA dans un processus à part entière et à faire surveiller votre système d'exploitation.

La bonne chose avec Lua est que vous n'aurez besoin d'aucune configuration de permission compliquée et dépendante du système d'exploitation pour Sandboxing: vous limitez-vous simplement la durée et la mémoire (raisonnables; sous Windows, il y a Objets de travail , Unix est ulimite - pertinent: Limitation de ressources Linux ), puis gardez des choses comme Os.execute, la moitié de la moitié du Io-bibliothèque et modules comme LuasCocket loin du Scriptter (assez facile).

Récupération des erreurs dans Code SandBoxed

Vous pouvez gérer presque tout (sauf la violation des délais / limites de mémoire) sans détremper votre interpréteur Lua: enveloppez simplement l'exécution du code fourni par l'utilisateur à l'intérieur d'un PCALL ; Si vous appelez des fonctions Lua-API qui pourraient vous échouer, vous devez les envelopper dans une fonction de PCALL, également (ou définir une fonction de panique Lua et la gérer de là).

[Je ne voulais pas que les gens se glisse sur ce fil supposent que Debug.Sethook est adéquat pour Sandboxing et Stackoverflow ne me laisserait pas commenter (encore)]


0 commentaires

0
votes

J'ai utilisé deux techniques pour résoudre ce problème. Le premier consiste à appeler la méthode DOFILE ou DOSTRING à l'intérieur d'une tâche distincte. De cette façon, vous pouvez abandonner le fil. Je ne connais aucune technique (disons d'un crochet) pour sortir de l'interprète.

Un autre moyen serait de configurer un AppDomain . En utilisant ceci, vous pouvez également définir des contraintes séparées (preuve et autorisation) voir Createdomain pour plus de détails.


0 commentaires

0
votes

Qu'en est-il de la définition de la ligne de ligne avant exécuter le code Lua? Je ne sais pas, est-ce possible en C #, mais il est possible dans l'original C Lua.

Est-ce que votre détecteur de boucle est déjà exécuté dans une tâche C # différente?

  • Si oui, utilisez la variable C # avec C # Crochet. Dans ce cas, votre détecteur de boucle et votre cochons de coche C # variable comme TerminAtelua et lancez Lua Error (il devrait être possible).
  • Si non, et vous détectez la boucle sur le côté Lua (également à l'aide de crochets?), Définissez la variable Lua (faites-la éteindre pour éviter les astuces d'utilisateur) et également lancer une erreur.

    Une partie importante consiste à ne pas réinitialiser cette variable (ni C # ou Lua) avant de vous assurer que vous êtes vraiment sûr de la finition de votre tâche, car l'utilisateur peut attraper votre erreur via PCALT et essayer de le gérer.


0 commentaires

1
votes

Mettez la boucle Lua à l'intérieur d'une coroutine et à la fin de chaque boucle, utilisez simplement la déclaration de rendement NULL pour attendre un cadre (permettant au fil du travailleur d'être exécuté).


0 commentaires

0
votes

Vous pouvez le faire comme ceci, si vous souhaitez détecter si une boucle est toujours en marche. XXX PRE>

La sortie sera la suivante: P>

Still running
Still running
Still running
Still running
Still running
Loop stopped running


0 commentaires