È la parte del mestiere che si usa di più e che si insegna di meno. Un programma che non funziona lascia molte più tracce di quante chi lo cerca di solito guardi.
Leggere l'errore
Quando un programma RPG va in errore, il job log contiene due cose distinte, e servono entrambe.
Il messaggio. RNQ sono le eccezioni che si fermano ad aspettare una risposta, RNX
quelle che terminano il programma. MCH sono errori del livello macchina — indice fuori
dai limiti, campo numerico che contiene qualcosa che numerico non è.
Lo stack delle chiamate. Dice quale programma, quale procedura e quale numero di istruzione. È l'informazione che porta dritti al punto, e viene ignorata quasi sempre.
DSPJOBLOG JOB(123456/MROSSI/CHIUSURA)
Su un job ancora attivo, lo stack si guarda con WRKJOB, opzione 11.
Consiglio
compilando con OPTION(*SRCSTMT) il numero che compare nel messaggio è il
numero di riga del sorgente, non un numero interno da riconvertire. È un parametro che
costa niente, e senza il quale metà dell'informazione dell'errore va sprecata. Vale la
pena metterlo come impostazione predefinita in tutto ciò che si compila.
Gli errori gestiti dal programma
Un programma può accorgersi da solo di un errore invece di morire. Due modi.
MONITOR, che è la forma moderna e vale per un blocco:
monitor;
chain (numero) ordini;
if not %found(ordini);
// record assente: caso previsto
endif;
on-error;
// qualunque errore dentro il blocco
esito = 'Errore in lettura ordini';
endmon;
*PSSR, la subroutine di errore del programma, che raccoglie tutto quello che non è
stato gestito altrove ed è l'ultima rete prima della fine.
Avvertenza
una *PSSR che si limita a return trasforma un guasto in un silenzio.
Il programma finisce, il job risulta terminato normalmente, e il dato non è stato
scritto. È il modo in cui nascono le chiusure che "sono andate bene" e hanno lasciato
l'archivio a metà. Qualunque cosa faccia la *PSSR, deve lasciare traccia: un messaggio
in coda, una riga in un file di log, un codice di ritorno che chi ha chiamato controlla.
Il debugger
Il debugger ILE lavora sul sorgente, purché il programma sia stato compilato con le informazioni necessarie:
CRTBNDRPG PGM(PRODLIB/FATTURE) DBGVIEW(*SOURCE)
*SOURCE mostra il sorgente originale, *LIST il listato dopo l'espansione delle copie e
della precompilazione SQL — che è quello che serve quando il problema è dentro un /COPY o
dentro un EXEC SQL.
STRDBG PGM(PRODLIB/FATTURE) UPDPROD(*YES)
Poi si mette un punto di interruzione (F6 sulla riga), si esegue il programma, e ci si ferma lì: F10 esegue un'istruzione, F12 riprende, F11 mostra il valore della variabile su cui è il cursore.
Avvertenza
UPDPROD(*YES) serve per lavorare su file di produzione, e va scritto
consapevolmente. In debug si eseguono le istruzioni davvero: se il programma scrive, il
record viene scritto. Provare su una libreria di collaudo, con OVRDBF che punta ai dati
di prova, è la differenza fra un debug e un incidente.
Il job che non è il tuo
È il caso più frequente e il meno conosciuto: il problema è in un job batch, che parte di notte, e nel debugger bisogna entrare da fuori.
STRSRVJOB JOB(123456/MROSSI/CHIUSURA)
STRDBG PGM(PRODLIB/CHIUSURA) UPDPROD(*YES)
Da quel momento i comandi di debug valgono su quel job: si mettono i punti di interruzione,
si rilascia il job, e ci si ferma nel punto giusto dentro l'elaborazione vera. Alla fine si
chiude con ENDDBG e ENDSRVJOB.
Consiglio
su un lavoro schedulato che fallisce solo di notte, la strada è sospendere
la voce di schedulazione, sottomettere il lavoro a mano a una coda tenuta ferma,
agganciarsi con STRSRVJOB e poi rilasciarla. Si ottiene lo stesso job, nello stesso
ambiente, con qualcuno davanti.
Il dump
Quando il problema non si riproduce, resta la fotografia:
dump(a);
DSPJOB opzione 11 sul job attivo, oppure il file di spool QPPGMDMP prodotto da un
programma terminato in errore, mostrano il contenuto di tutte le variabili nel momento del
guasto. Su un errore che capita una volta al mese è l'unica informazione che si ha.
Le tre cose che risolvono più casi
Guardare il primo errore, non l'ultimo. In un job log lungo i messaggi finali descrivono un programma già in difficoltà. Il messaggio che spiega è il primo grave.
Controllare che l'oggetto corrisponda al sorgente. Prima di leggere il codice riga per
riga, DSPOBJD ... DETAIL(*SERVICE) dice quando è stato compilato l'oggetto e da quale
sorgente. Un'ora persa a cercare un errore in un codice che non è quello che gira è
un'esperienza che si fa una volta sola.
Guardare l'ambiente prima del programma. Lista librerie del job, sovrascritture attive, gruppo di attivazione, iASP impostato. Una parte consistente dei guasti che sembrano di programmazione sono di ambiente, e il programma è innocente.
Commenti
Nessun commento ancora. Sii il primo a commentare!
Devi avere un account per commentare. Accedi · Registrati