Réparer des scripts automatiquement

Répondre
Partager Rechercher
Il arrive parfois que des scripts puissent s'arrêter d'eux-même à cause d'erreurs. Le run-time error qui peut être le résultat de plusieurs choses va mettre le script en "not running" et ne continuera pas de fonctionner correctement.

Il peut s'agir d'une collision entre la stack et la heap lorsque le script demande une mémoire trop importante, d'une erreur de calcul comme diviser un nombre par zéro (même si en théorie ce calcul est tout à fait possible, il en résulte un nombre infini).

Le problème est qu'il est impossible de ré-activer automatiquement par script un autre qui vient d'être stoppé par un run-time error, la fonction llSetScriptState et llResetOtherScript par exemple ne fonctionnera pas.

Il est par contre tout à fait possible de ré-activer un script après le redémarrage de l'objet (re-rez, re-wear). Voici les 2 scripts en question :


Repair Listener (à mettre dans un autre prim que le root)
Code PHP:

InitConnection() {
        
    
llListenRemovegListenId );
    
gListenId llListenDEBUG_CHANNEL""llGetLinkKey(LISTEN_LINK), "" );   // on active l'écoute du linked prim correspondant sur DEBUG_CHANNEL
}



integer IC_SCRIPTREP_ADD = -258954// adresse du script qui va s'occuper de reset
integer LISTEN_LINK 1// 1 = root prim


integer gListenId;


default
{
    
    
on_rezinteger p ) { InitConnection(); }
    
state_entry() { InitConnection(); }
    
    
    
listeninteger chanstring namekey idstring msg ) {
        
        if( ~ 
llSubStringIndex(msg"run-time error") ) // si "run-time error" est présent dans msg alors on envoie le nom du script par linked message 
            
llMessageLinkedLISTEN_LINKIC_SCRIPTREP_ADDllGetSubString(msgllSubStringIndex(msg":")+1llSubStringIndex(msg"]")-1), NULL_KEY );
        
    }






Repair Core (à mettre dans le root prim)
Code PHP:

AddScriptstring scriptName ) {
    
    if( !~ 
llListFindList(gScriptList, [scriptName]) ) { // si le nom n'est pas déjà présent dans la liste, on l'ajoute
            
gScriptList += scriptName
            
llOwnerSayscriptName " sera reset au prochain demarrage." );       
    }  
    
}


RepairScript() {
    
    
integer m = (gScriptList!=[]); // on compte le nombre de noms dans la liste
    
string scriptName;
    
    while( ~--
) {
            
         
scriptName llList2StringgScriptList); // on récupère le nom de la liste
         
         
if( llGetInventoryType(scriptName) == INVENTORY_SCRIPT ) { // si le script est bien présent dans l'inventaire et qu'il s'agit bien d'un script
                    
                
llOwnerSay"Reset : " scriptName );
                
llResetOtherScriptscriptName ); // on reset
                
llSetScriptStatescriptNameTRUE );  // on le reactive
         
}
    } 
          
    
    
gScriptList = []; // on vide la liste
    
}



integer IC_SCRIPTREP_ADD = -258954// adresse pour ajouter un script

list gScriptList// liste des scripts à reset

default
{
    
    
    
on_rezinteger p ) {  RepairScript();  }
    
    
link_messageinteger linkinteger adressstring datakey data2 ) {
        
        if( 
adress == IC_SCRIPTREP_ADD // on reçoit une demande d'ajout de script à reset
              
AddScriptdata ); 
        
    }




Le fonctionnement :

Le principe est très simple, j'utilise dans un premier temps "Repair Listener", il s'agit d'un script qui va écouter le DEBUG_CHANNEL (là où les erreurs sont envoyées). Il faudra mettre ce script dans un autre prim que celui où vous souhaitez réparer vos scripts (la raison est qu'un prim ne peut pas s'écouter lui-même quand il envoie des messages dans un canal). Il va envoyer le nom du script qui a une erreur type "run-time error" au Repair Core.

Le Repair Core, lui, va s'occuper de stocker les noms reçus dans une liste puis les reset/activer au prochain démarrage de l'objet, c'est à dire quand :

- Vous re-portez l'objet
- Vous re-rezzez l'objet

Si vous ne comprenez pas tout, demandez-moi de réexpliquer ou si vous avez une meilleur méthode que celle-là, merci de la partager .
Est-ce que tu pourrais expliciter le fonctionnement de cette ligne :

Code PHP:

    integer m = (gScriptList!=[]); // on compte le nombre de noms dans la liste 

Merci
Citation :
Publié par bestmomo
Est-ce que tu pourrais expliciter le fonctionnement de cette ligne :

Code PHP:

    integer m = (gScriptList!=[]); // on compte le nombre de noms dans la liste 

Merci
m = (gScriptList!=[]); est exactement la même chose que m = llGetListLength(gScriptList) mais sans fonction, c'est une astuce que je me suis habitué à utiliser. Avant mono c'était un gain de performance maintenant je pense pas mais ça reste une habitude (je trouve ça plus rapide à écrire ).


Code PHP:

integer len = (list != []); 
//signifie la même chose que : 
integer len llGetListLength(list);

integer len = ([] != list);
//signifie la même chose que :
integer len = -llGetListLength(list);


integer len = ~([] != list);
// signifie la même chose que :
integer len llGetListLength(list) - 1;

// etc.. 
Plus d'infos : http://wiki.secondlife.com/wiki/LSL_Hacks

(Note: au lieu de retourner VRAI ou FAUX dans cette condition, tu vas avoir le nombre de données dans la liste.)
Citation :
Publié par Seb_01
astucieux et utile

J'étais persuadé que l'écoute de DEBUG_CHANNEL était impossible. Mauvais lecture de ma part.
Merci . Il est possible de parler et écouter dans le DEBUG_CHANNEL. Au moment d'un run-time error, l'objet où est placé le script va parler dedans et indiquer le nom de celui-ci.

Exemple d'une erreur de collision entre la stack et la heap :

Citation :
Object: Object [script:New Script] Script run-time error
Object: Stack-Heap Collision
Je récupère le nom entre ":" et "]".



Exemple complet :

Citation :
[7:03] [DEBUG_CHANNEL] root_prim: root_prim [script:testError] Script run-time error
[7:03] [DEBUG_CHANNEL] root_prim: Stack-Heap Collision
[7:03] root_prim: testError sera reset au prochain demarrage.

-- Re-rez de l'objet --

[7:05] root_prim: Reset : testError

et ainsi de suite...

En ayant crée un objet de 2 prims :
- root_prim
- 1st_link

Repair Listener dans le 1st_link
Repair Core dans le root_prim

Puis placé le script testError dans le root_prim :

Code PHP:

default
{
    
state_entry() {
        list 
t;
        while( 
TRUE )
            
+= [llGetOwner()];
    }
   

Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés