Mastodon

Negli articoli precedenti abbiamo già parlato del comando fileevent.

In questo articolo vedremo come utilizzare questo comando per mettere in comunicazione diversi processi.

Il termine processo è da intendersi come sinonimo di programma.

La comunicazione tra processi non dovrebbe suonarci cosa nuova. Facciamo un esempio: un processo potrebbe ricevere l’input da un utente tramite lo standard input e un altro processo potrebbe catturare e poi gestire questi dati, o comandi, per mostrare un certo risultato sullo standard output.

Esempio

Iniziamo con lo scrivere il primo programma.

Primo programma

# Firts Program

for {set i 0} {$i < 10} {incr i} {
    after 1000
    puts $i
    flush stdout
}

In questo primo programma utilizziamo il comando flush per essere sicuri di svuotare il buffer dello standard output.

Passiamo ora al secondo programma.

Secondo programma

# Second Program

proc getline {chan} {
    global done

    gets $chan line

    if { ! [eof $chan] } {
        puts ">> $line"
    } else {
        close $chan
        set done 1
    }
}

set program [open "|tclsh calc.tcl" r]
fileevent $program readable [list getline $program]
fconfigure $program -buffering line

vwait done

Cerchiamo di capire questo codice.

La procedura getline riceve un unico argomento: l’identificativo del canale da cui poter leggere i dati.

Quando questa procedura viene invocata, legge una prima stringa e procede al suo controllo: se la condizione di fine file (intercettata grazie al comando eof) non si realizza, allora la stringa viene rimandata allo standard output (lo schermo), altrimenti il canale viene chiuso, ovvero viene interrotta la connessione con il processo esterno.

Inoltre alla variabile globale done viene cambiato il suo valore e questa modifica segnala l’evento al comando vwait che fa ripartire lo script che era stato messo in pausa.

Nell’articolo Come avviare altri programmi da Tcl avevamo visto che per avviare un processo esterno possiamo utilizzare due differenti comandi: exec e open.

Nel nostro caso per avviare il processo esterno calc.tcl utilizziamo il comando open perché ci permette di comunicare con lui.

Come forzare la chiusura del canale con un processo esterno

Supponiamo che un processo esterno non dia più segni di vita, in questo caso possiamo gestire la chiusura forzata del canale che avevamo stabilito con lui, dopo un determinato periodo di tempo da noi prestabilito.

Attenzione! La modalità di chiusura forzata di un processo esterno dipende dal sistema operativo in uso e quindi è bene limitarsi alla sola chiusura del canale.

# Close the channel after 100 seconds...
after 100000 {
    catch {
        close $program
    }
    set done 1
}

L’uso del comando catch è necessario per evitare possibili problemi al nostro programma in quanto la chiusura forzata del canale genera un errore che in questo modo catturiamo noi evitando che venga inviato al gestore degli errori standard del sistema operativo.

Nota: l’uso del comando after rende i nostri scripts in linea con lo stile specifico della programmazione a eventi.


Nel prossimo articolo tratteremo il tema legato alla gestione dell’ora e della data.