Aller au contenu

Instruction RPG full free · IBM i (AS/400) · Procédures, sous-programmes et erreurs

ON-EXIT

Nettoyage à la sortie d'une procédure

Déclare, à la fin d'une procédure, un bloc exécuté à chaque sortie, que la procédure se termine normalement, par un RETURN anticipé ou par une erreur.

Syntaxe

ON-EXIT {indicateur};
  instructions de nettoyage
END-PROC;
indicateur
Zone indicateur facultative. Elle vaut *ON si la procédure se termine à cause d'une erreur, *OFF sinon.
Effet
L'indicateur, s'il est donné, est positionné avant l'exécution du bloc : *OFF pour une sortie normale, *ON pour une sortie sur erreur. L'ON-EXIT s'exécute avant que l'appelant ne reprenne la main.

À quoi ça sert

Une procédure qui ouvre un fichier, réserve un verrou ou crée un objet temporaire doit le libérer sur tous ses chemins de sortie : fin normale, plusieurs return anticipés, erreur. Au lieu de dupliquer le nettoyage avant chaque return, on l'écrit une seule fois dans ON-EXIT.

Le bloc se place à la fin de la procédure, juste avant END-PROC. Dans le premier exemple, il s'exécute aussi bien après la sortie normale du client 100 qu'après le return *off anticipé du client 0.

Exemple 1 : Nettoyage après sortie normale et après RETURN anticipé

**free
// ON-EXIT : bloc de nettoyage execute a la sortie d'une procedure, quelle que soit la sortie.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-pr traiter ind;
  numcli packed(5:0) const;
end-pr;

dcl-s ok ind;

snd-msg 'Appel 1 : client 100';
ok = traiter(100);
snd-msg 'Resultat : ' + %char(ok);

snd-msg 'Appel 2 : client 0 (refuse)';
ok = traiter(0);
snd-msg 'Resultat : ' + %char(ok);

*inlr = *on;

dcl-proc traiter;
  dcl-pi *n ind;
    numcli packed(5:0) const;
  end-pi;
  dcl-s arret ind;

  snd-msg '  Ouverture de la ressource pour ' + %char(numcli);
  if numcli = 0;
    snd-msg '  Client invalide, sortie anticipee';
    return *off;
  endif;
  snd-msg '  Traitement du client ' + %char(numcli);
  return *on;

on-exit arret;
  snd-msg '  ON-EXIT : fermeture, sortie anormale = ' + %char(arret);
end-proc;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Appel 1 : client 100
  Ouverture de la ressource pour 100
  Traitement du client 100
  ON-EXIT : fermeture, sortie anormale = 0
Resultat : 1
Appel 2 : client 0 (refuse)
  Ouverture de la ressource pour 0
  Client invalide, sortie anticipee
  ON-EXIT : fermeture, sortie anormale = 0
Resultat : 0

Les deux appels affichent « ON-EXIT : fermeture ». Dans le second, la procédure sort par return *off sans avoir atteint la fin, et le bloc est exécuté quand même. L'indicateur vaut 0 dans les deux cas : aucune erreur.

Exemple 2 : Sortie anormale et ordre d'exécution

**free
// ON-EXIT : sortie anormale (erreur) et ordre d'execution avec le MONITOR de l'appelant.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-pr moyenne packed(9:2);
  total packed(9:2) const;
  nombre packed(3:0) const;
end-pr;

dcl-s resultat packed(9:2);

monitor;
  resultat = moyenne(1250.50 : 0);
  snd-msg 'Moyenne : ' + %char(resultat);
on-error;
  snd-msg 'MONITOR de l appelant : erreur, statut ' + %char(%status);
endmon;

resultat = moyenne(1250.50 : 4);
snd-msg 'Moyenne : ' + %char(resultat);

*inlr = *on;

dcl-proc moyenne;
  dcl-pi *n packed(9:2);
    total packed(9:2) const;
    nombre packed(3:0) const;
  end-pi;
  dcl-s anormal ind;

  snd-msg '  Calcul de ' + %char(total) + ' / ' + %char(nombre);
  return total / nombre;

on-exit anormal;
  snd-msg '  ON-EXIT : sortie anormale = ' + %char(anormal);
end-proc;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

  Calcul de 1250.50 / 0
  ON-EXIT : sortie anormale = 1
MONITOR de l appelant : erreur, statut 202
  Calcul de 1250.50 / 4
  ON-EXIT : sortie anormale = 0
Moyenne : 312.62

Le premier appel divise par zéro dans la procédure. Le ON-EXIT s'exécute en premier, avec l'indicateur à 1, et ensuite seulement le ON-ERROR du MONITOR de l'appelant, avec le statut 202. Le second appel, valide, termine avec l'indicateur à 0.

Le piège

L'ON-EXIT passe avant le traitement d'erreur de l'appelant. Dans le deuxième exemple, l'ordre affiché est : calcul, ON-EXIT (indicateur à 1), puis « MONITOR de l'appelant ». Le bloc de nettoyage ne doit donc pas dépendre de ce que l'appelant fera de l'erreur. Gardez-le court et sûr : une instruction qui échouerait dans le nettoyage ferait oublier l'erreur d'origine.