Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

10
voti

Under the bug

Bug. Sovente accade, nella traduzione della lingua anglo sassone, che non esistano parole italiane perfettamente sovrapponibili nel significato. Bug viene tradotto letteralmente con Baco ma questo è sempre un termine all'appannaggio di chi lavora nel settore, infatti come il termine inglese, ne riprende l’eccezione.

Le prime tre righe di wikipedia spiegano dicendo:“Nell'informatica il termine bug o baco identifica un errore nella scrittura di un programma software. Meno comunemente, il termine bug può indicare un difetto di progettazione in un componente hardware, che ne causa un comportamento imprevisto o comunque diverso da quello specificato dal produttore.”

Scrivo funzioni in modo che non siano più grandi di 40 di righe, questo mi permette di avere una sezione di codice completa a vista d’occhio.

Quaranta erano le righe che il mio IDE visualizzava ( senza spostare la barra laterale) e sono abbastanza per scrivere il 90% delle procedure di un software ( ecco .. se siete capaci ditemi come si fa ). Con l’avvento di Windows e dei font true type che diedero inizio all'era del WISIWYG ( acronimo di oltreoceano What you see is what you get usato per identificare tipicamente quelle applicazioni che ti permettevano di vedere su schermo quello che poi si sarebbe stampato su carta ) uso sempre l’Arial 10 di colore nero con sfondo bianco.

Un tempo il contrasto era sempre rovesciato. I caratteri di colore verde fosforescenti erano fatti con tubi catodici a fosfori ad alta persistenza. Le frequenze di aggiornamento dei trasformatori di riga erano un po’ bassine così pensarono bene di aumentare il tempo di persistenza dei fosfori sul tubo, per diminuire il tremolio dell’immagine. Come dire, parlando metaforicamente, se Maometto non va alla montagna, la montagna va a Maometto ( n.b. il proverbio vero ha i termini invertiti... )

Se avevi così l’ardire, di modificare le impostazioni del programma e rovesciare il contrasto, impostando il carattere nero su uno sfondo verde fosforescente, dopo poco, inevitabilmente, subivi pesanti effetti fisici collaterali difficilmente reversibili tipo: arresto psicomotorio, perdita di identità, disturbi bipolari, attacchi epilettici e via di seguito. Per qualche periodo, tentai anche sotto Windows di mantenere questo tipo di contrasto ( carattere bianco su fondo nero ) ma la debole luminosità del carattere grafico rendeva difficile la visualizzazione del testo e alla lunga ebbi gli stessi effetti di prima ( arresto psicomotorio, perdita di identità... ).

Mi giocai la carta della pensione per lavoro usurante ( alla stessa stregua del lavoro in miniera, catena di montaggio... ) ma non ci riuscii e così sono ancora qui a scrivere software...
Un tempo c’era un editor chiamato Brief. I poveracci scrivevano il codice con l’edit del dos, chi lavorava su Unix usava il Vi credendo di lavorare con una seria applicazione di testo. I programmatori professionisti usavano il Brief. Se non l’avevi lo compravi... se non lo compravi lo copiavi. Aveva le finestre dimensionabili e potevi nello stesso schermo, vedere più sezioni di codice di diversi moduli contemporaneamente. Unico nel suo genere aveva la possibilità di selezionare colonne di testo. Diventò uno standard fra i programmatori tanto che, ad esempio, Visual Studio 6 permetteva di impostare l’editor con gli stessi shortcut key ( combinazioni di tasti ) del Brief.

Veniamo al nostro post. Questa volta diversamente dagli altri racconti prenderemo in considerazione tre tipologie di baco software/firmware che possono capitare durante lo sviluppo di un progetto. Questi bachi li chiameremo:

  • baco sulla fiducia
  • baco presunto
  • baco specialistico


Baco sulla fiducia

Franck ... se ti chiedo "gli errori" e tu dici "non funziona", non andiamo molto d'accordo ... ( nessuno )
Il progetto embedded è stato sviluppato con un compilatore C della Microchip su un micro st32. Il firmwarista doveva travasare il software ( e fare qualche modifica ), aggiungendo dei moduli per alcune interfacce hardware che erano state aggiunte. Il modulo software in questione quindi era già provato,testato e perfettamente funzionante. Ad un certo punto durante le fasi di download, del firmware, doveva essere calcolata la checksum. Questo calcolo veniva fatto all'interno di un ciclo for dichiarato così:
for (i=0; i<=fwsize; i+=2)
{

Crc = chBufferFw[i];
calcolo..

}

Con il travaso sul nuovo hardware, il calcolo della CRC non risultava più corretto. Il baco consisteva in un effetto collaterale ad un problema notorio del C che è l'inesistente controllo del tipo di dato. A seguito di questo mancato controllo il C consente il confronto fra variabili di tipo diverso. Per la precisione erano dichiarate così:

int i = 0;
unsigned long fwsize=0 ;

Il ciclo, come si può ben capire, funziona correttamente fintanto che i valori della variabile fwsize sono inferiori a 32767. I confronti con tipi di dato diversi è uno dei “problemi” impliciti del C. Diciamo che tipicamente un compilatore, un warning su una linea di codice, di questo tipo, dovrebbe sempre darlo. Purtroppo questa cortesia non è accaduta e così lo sventurato ha perso una buona mezza giornata, diagnosticando improbabili problemi sul calcolo CRC, perso fra tabelle checksum e relative criptiche funzioni.
Il round tips di questo bug potrebbe essere quello di acquisire la notazione ungara. Questa notazione è una specie di metodo per la stesura del codice. Applicandolo il programmatore si obbliga ad usare una nomenclatura delle variabili un po' più rigorosa. In pratica, questo metodo consiste nell'aggiungere un suffisso che ne descriva il tipo. Facciamo qualche esempio ripreso da wikipedia:

nSize: numero intero
cApples: conteggio degli elementi
dwLightYears: double Word
bBusy: booleano
fBusy: flag booleano
pFoo: puntatore
szLastName: Stringa terminata con zero
rgStudents: Array o range

Ora io mi sono preso delle licenze poetiche storiche tanto da aver sviluppato un dialetto della notazione ungara che è diventato col tempo così:

iSize: numero intero
ulDimX: long senza segno
dwLightYears: double Word
bBusy: booleano
fBusy: float
pFoo: puntatore

etc... etc...

il codice suddetto seguendo la mia licenza poetica sarebbe diventato:

for ( iNdx = 0 ; iNdx <= ulFwSize ; iNdx += 2)
{

iCrc = chBufferFw[iNdx];
calcolo...

}

Faccio una piccola parentesi sulla scrittura dei programmi. Quando scrivo software indento ad ogni test condizionale, mettendo la parentesi graffa allineata con il test e il codice avanzato di un tab in questo modo:
if(<test condizionale>)
{

istr1;
istr2;
if(<test condizionale>)
{
istr1;
istr2;
}

}

Il termine Indento non è un errore di battitura ma deriva dal verbo indentare, che significa mettere i denti ( cit. Treccani ) ma in questo caso ha il senso di allineamento.
Dicevamo che questa è una regola nella mia testa, tutto il mio codice è scritto così. Quando lo guardo mi sembra più ordinato, pulito, quasi a scongiurare qualsiasi evento degenere.
Spesso, quando l’algoritmo diventa complicato, lo sviluppo del software ci potrebbe costringere ad annidare diversi livelli di parentesi.

Durante le fasi di debugging, aggiungendo e togliendo codice in stato epilettico compulsivo da baco, se si perde cancellando per sbaglio una parentesi graffa, si creano piccoli prostranti incubi. Questo accade perché il C, proprio per come è strutturato il linguaggio, non riesce a rilevare la condizione di inizio o termine del ciclo, la dove si è creato. Gli errori, spesso criptici, potrebbero avvenire centinaia di righe dopo la mancata parentesi o addirittura anche in moduli diversi. Con questo allineamento, riesco agevolmente ad associare la loro corretta apertura e chiusura seguendo semplicemente l’indentazione.
I programmatori della Microsoft in tutti i loro esempi su web, invece la prima parentesi la mettono al termine del test condizionale e il test di prima per loro diventa così:

if(<test condizionale>) {

istr1;
istr2;
if(<test condizionale>) {
istr1;
istr2;
}

}

Dopo essermi giocato il posto alla Microsoft, riprendiamo il discorso della notazione ungara allargandolo alla dichiarazione delle variabili. Queste dovrebbero essere fatte in modo da richiamare l’uso a cui sono previste. Se la variabile del ciclo for la utilizzo come indice di un vettore, la chiamerò in un modo che mi ricordi per quale motivo mi serve, nel nostro esempio potrebbe essere chiamata così iIndexVect. Le dichiarazione minimaliste tipo ‘i’ ‘b’ o ‘xy’ sono troppo essenziali e vanno bene solo per dei registri di un micro però, dal lato opposto, bisognerebbe evitare anche di essere troppo prolissi. Nomi di variabile del tipo “NumerdoDiConteggiMensili” sono in genere inutili e alla fine si ottiene l’effetto contrario, perché rendono il codice pesante da leggere e per questo in genere sconsigliati.

Il pregio della notazione ungara è quello di rendere evidente al firmwareista il tipo di variabili utilizzate, e quindi il loro uso improprio. Con un colpo d’occhio, diventa chiara la porcata che il C rende legittima, quella appunto di confrontare impunemente, dati di tipo diverso.
Una delle massime regole, del buon debugger è quella di non dare mai troppa fiducia ai compilatori.

Baco presunto

- ciao a tutti,so che si può sviluppare in iOS solo con una macchina apple,c'è qualche modo per ovviare a questo problema?
- link con una macchina virtuale su windows
- cioè devo virtualizzare iOS sul pc!? una delle procedure più complicate! non c'è un modo più semplice?
- Comprati un Mac
( forum Html.it )

Prima di parlare del baco presunto volevo raccontare un piccolo aneddoto perché, come qualcuno ha già capito, sono un tipo che ogni spesso je rode...

Ieri sono andato in banca per le pulizie di primavera, togliere le ragnatele dal conto, sentire l’eco del vuoto creato dall'inflazione e così via. La direttrice ha chiesto di incontrarmi per capire chi fossi, vista la mia naturale refrattarietà ai contatti sociali, di qualsiasi tipo. Dopo i primi convenevoli si parlottò del più e del meno con discorsi alla deriva senza un particolare filo logico. Parlai di una recente avventura negativa avuta con le poste.

Lei annui piuttosto compiaciuta, lamentandosi a ruota, che l'istituto dovrebbe fare il mestiere di postini o portalettere e non di gestire il denaro della gente ( e fregare i clienti alle banche ). Coerentemente con quanto affermato, di li a poco tentó di rifilarmi con tecniche coercitive, una nuovissima e convenientissima, polizza di assicurazione sulla casa.
Diciamo che ebbi una sorta di disagio peró non ebbi il coraggio di stroncarle l'entusiasmo che mise nel propormi questo prodotto finanziario. Debolemente incuriosito, mi sono fatto dare il prospetto informativo e la sera anziché leggermi un buon libro, ho dato un occhiata agli articoli e le varie clausole.

Stentavo a credere ai miei occhi e a quello che c’era e c’è scritto, così cito il documento che ufficialmente è stat redatto dalla Avipop assicurazioni s.p.a. modello PN 026627/B ed. 04/2012 pagina 6 di 22., al suo interno infatti si legge:

Articolo 1.8
Sono esclusi dalla assicurazione…
f) danni causati da guerra civile con o senza dichiarazione,
 insurrezioni, invasioni e ostilità... trasmutazione del 
nucleo di atomo nonché da radiazioni provocate
dall'accelerazione artificiale di particelle atomiche 
e da esposizione a radiazioni ionizzanti;

e fin qui inevitabilmente sorrido, perché chi ha scritto questo rimando è uno che davvero crede in quello che fa... poi il testo continua

g) danni causati da terremoti, eruzioni vulcaniche,
 inondazioni,  alluvioni, allagamenti, mareggiate,
 frane e/o cedimenti del terreno valanghe e 
slavine...

e anche qui nessuno replicherebbe alla legittimità del mancato indennizzo, se non che al prossimo articolo

h) i danni di qualsiasi natura direttamente 
 od indirettamente derivanti da mancato,
 errato, inadeguato funzionamento e/o 
 elaborazione del sistema informativo 
 e/o di qualsiasi impianto apparecchiatura,
 componente elettronica, firmware, 
, hardware.

Questa sorta di malcelata associazione che accomuna il lavoro da firmwareista a quello di una calamità naturale, è veramente sintomatica. Il lavoro da programmatore, nell'immaginario collettivo, è considerato alla stessa stregua di un pianeta che entra in collisione con la terra o ad un l’esplosione di un super vulcano che sommerge di lava l’intero globo terraqueo.

Mi chiedo, ma tutte quelle storie relative al controllo qualitativo del software dove sono andate a finire ? Le ISO sul software ? La documentazione di progetto ? Evidentemente non sono bastate e la compagnia di assicurazione, che di previdenza se ne intende, ha pensato bene di risolvere la questione alle origini del problema. Se la casa ti piglia fuoco perché nella caldaia c’è un baco, semplicemente ti arrangi e forse, in questo caso, si potrebbe anche usare un altro intercalare, ma siamo dei gentiluomini...

Dopo essermi fatto la mia quotidiana rosicata... riprendiamo la storia del Baco presunto. Nella spiegazione di baco citata da Wikipedia si includeva anche una estensione del significato meno comune, che riprendo:

...Meno comunemente, il termine bug può
 indicare un difetto di progettazione 
in un componente hardware, che ne causa
 un comportamento imprevisto o comunque 
diverso da quello specificato dal produttore.

In questo esempio, considereremo un tipo di baco in questa eccezione migliore. Il cliente era una nota azienda di elettrodomestici ed aveva richiesto un sistema embedded per il controllo del suo condizionatore domestico. Il progetto firmware era già consolidato da tempo e fu inserito in questa nuova piattaforma, che però aveva lo stesso microcontrollore dei precedenti progetti.

Le funzioni più o meno erano le solite: un controllo ventola con pid a taglio di fase, un ingresso tachimetrica con frequenza 20Hz -2 KHz, un controllo per un motore passo passo dedicato al deflettore, una interfaccia seriale ad infrarossi per il telecomando, un paio di ingressi analogici per la lettura di due sonde temperatura NTC, un uscita relè per il compressore e poco altro...

Il cliente installò la scheda su un nuovo prototipo, ma dopo 6 mesi di funzionamento corretto, la macchina andava sistematicamente allarme di NTC in corto. In questa condizione il firmware si suicidava disattivando il condizionatore senza possibilità di ripristino. In realtà le possibilità di ripristino c’erano; spegnendo e riaccendendo, la macchina, l'utente riusciva infatti a far riprendere il suo funzionamento corretto.
Ma in questa condizione però poteva durare solo una decina di minuti, passato questo tempo si ripeteva lo stato di errore sulla NTC che provocava il nuovo arresto.

Il modulo Ntc, era composto da due parti di codice differenziate. Una parte, era dedicata alla misura, a cui veniva associata una funzione di linearizzazione con spezzate. Nella seconda parte, venivano invece, attivati e disattivati i flag di sistema a seconda della temperatura raggiunta. Sui margini del range operativo, avevamo quindi implementato gli allarmi di Ntc Aperta e Ntc in corto.

Questi margini, previsti, erano -20°C e +60 °C, limiti sovrabbondanti per una temperatura interna ad una tipica stanza italiana. Il progetto iniziale, che prevedeva inizialmente l’utilizzo della sola temperatura ambiente, in corso d’opera fu soggetto ad una modifica che rendeva necessaria l’implementazione di una sonda in grado di misurare anche la temperatura della batteria esterna.

I margini dichiarati di utilizzo della batteria erano di -10°C e 50°C range che comunque garantiva l’utilizzo dello stesso modulo per il secondo tipo di sonda.

Il modulo nuovo però doveva essere utilizzato per una nuova serie di condizionatori di potenza frigorifera superiore. Nei condizionatori d’aria c’e un parametro che definisce appunto la potenza frigorifera dell’elettrodomestico, questo parametro è definito dalla sigla BTU ( British Termal Unit).

Una BTU è definita dalla quantità di calore 
richiesta per alzare la temperatura di 1 libbra 
(ovvero 453,59237 grammi) di acqua 
da 39 °F a 40 °F (3.8 °Ca 4.4 °C) 
il BTU all'ora (BTU/h) è l'unità di potenza 
associata alla BTU: 1 cavallo vapore è 
approssimativamente pari a 2540 BTU/h1 
watt è approssimativamente pari a 3,412 BTU/h 
1000 BTU/h sono quindi approssimativamente 
pari a 293 W1 Frigoria/h = 3,97 BTU/h
 ( wikipedia )

In italia esiste la misura definita frigoria molto più efficiente e pratica, però in questo sistema sfaccim dove si globalizza considerando le cose non con la testa ma con altre parti del corpo, si preferiscono i cavalli fatti a vapore, le iarde ai metri le libbre ai chilogrammi.

"la frigoria è  la quantità di calore che deve essere sottratta da un 
chilogrammo d'acqua per abbassarne la temperatura da 15,5 °C a 14,5 °C
alla pressione di 1 atmosfera”. ( wikipedia ) 

Il sistema economico prendendo il sopravvento sulle persone ha stabilito di imperio che il parametro BTU venga utilizzato come misura termica.

I condizionatori tipicamente avevano poche migliaia di BTU e i modelli di punta a quel tempo, vantavano l’astronomico target da 9000 btu. Il miglior rendimento dei compressori, associato a nuove ingegnerizzazioni delle batterie, utilizzate per la dissipazione del calore, permise lo sviluppo industriale di nuovi condizionatori con potenze frigorifere (?) impensabili che raggiunsero così i target attuali da 12000 BTU, ampiamente sufficienti per appartamenti di medio piccole dimensioni.

Ritorniamo al nostro racconto. Cosa poteva causare un problema sulla lettura di temperatura dopo sei mesi di funzionamento corretto ? Quale problema logico nel firmware poteva causare questa anomalia ?Dove era il baco ?

In questo caso il firmware faceva quello che doveva fare, il vero problema nasceva da una diversa implementazione del sistema di controllo. Così come spiega la citazione iniziale, il baco nella sua estensione è qualcosa che non deve essere necessariamente legato ad un problema software. L’apparato era stato inserito sopra una macchina più performante con diverse specifiche o per meglio dire con differenti limiti di targa. Il calore della batteria esterna del nuovo condizionatore, durante il periodo invernale, non aveva dato problemi.

Durante il primo periodo estivo le cose andarono bene sino a quando, verso luglio nei giorni più caldi dell’alta Brianza, le temperature della batteria esterna aumentarono, superando il limite tale per cui raggiunto un valore di resistenza limite, veniva rilevata la condizione di NTC in corto ( 60 °C ).

Per questo tipo di bachi, che potremo appunto chiamare presunti, non ci sono round tips. Sono bachi di progetto e non di firmware che accadono tipicamente quando non si conosce bene il sistema e le sue risposte funzionali. Questi bachi sono in genere direttamente proporzionali al numero di persone che mettono bocca sul progetto. In questo caso per risolverlo, si è semplicemente reingegnerizzato il modulo modificando la lettura analogica per implementare l’allarme NTC in corto, in modo più efficace con temperature equivalenti molto più alte.

Baco specialistico

drew99: Dichiaro un array dinamico multidimensionale grande 65536 * 65536, ma il programma non riesce ad inizializzare l'intero array....
ixamit: 65536 * 65536 * 4 (32bit) = 17.179.869.184 bytes - sono un po' troppi in RAM
( forumo iprogammatori.it )


Le sezioni di codice implementato hanno peculiari punti deboli. Alcuni dovuti al linguaggio altri al firmwareista. Direi che un firmware strutturato di un sistema embedded ha in genere quattro sezioni di codice.

  • Sezione interrupt
  • Sezione ciclica
  • Sezione procedurale di ingresso
  • Sezione procedurale di uscita.

La sezione di interrput interagisce con le altre parti del software condividendo le risorse. Questa condivisione è anche la parte debole di questa sezione, perché chi legge è naturalmente desincronizzato rispetto da chi scrive. Per sapere quando ci sono stati gli aggiornamenti delle strutture dati condivise, si devono implementare semplici sistemi di semafori booleani. La sezione ciclica è quella che contiene meno bachi, perché piuttosto semplice da implementare.

Tipicamente in questo caso le parti deboli, sono quelle dove il firmwareista si trova più disagio. Se ad esempio abbiamo perplessità con i puntatori si cercherà di usarne il meno possibile.
Ovviamente questa è un esempio iperbole che possiamo associare solamente ad un novizio. Un firmwarista vero che lavora in C semplicemente non deve avere problemi.

Nelle sezioni di ingresso e uscita, risiede il 90% del codice, qui troveremo quasi tutti i bachi nelle loro forme più variegate e differenziate. Quello che considereremo però non è un progetto firmware ma bensì un progetto software su PC, scritto in Visual Studio 6.0. Si lo so il sistema è un po’ datato, i progetti in C++ dopo anni di indiscusso dominio stanno piano piano lasciando il passo, al più recente C#.

A chi interessasse in questa pagina della Microsoft vengono spiegate le differenze più importanti fra i due linguaggi ( link ). In questa pagina invece un elenco con il rating di popolarità dei linguaggi (link).
Noi invece parleremo, si di un software C++ sviluppato in modo particolare non ad oggetti ma a Thread, un modulo monolitico di circa 250.000 righe di codice. Per questo lo possiamo considerare come un abnorme sistema embedded degenerato.

Questo software era una specie di centro di raccolta dati, sviluppato per una delle tante aziende di servizi. Con le dovute proporzioni era un piccolo sistema di acquisizione di misure che dovevano essere prese dalle periferiche installate sul campo e “semplicemente” salvate in un database; il peggiore di tutti, Access. La semplicità della descrizione appena data è diventata inversamente proporzionale alla complessità algoritmica raggiunta.

Le migliaia di righe di codice, che con il tempo si sono aggiunte, sono diventate prima decine e poi centinaia di migliaia rendendo il software una sorta di mammut impazzito che sculetta dentro un negozietto di cristalli Swarovski.
Ma veniamo un attimo all'elemento importante di questo software, il thread.
La Microsoft aveva implementato nel sistema operativo di famiglia, Windows, la possibilità di creare queste fantomatiche strutture chiamate thread. Queste strutture erano riprese sempre dagli antesignani sistemi Unix che erano, al tempo, il riferimento principale delle applicazioni multitasking. In un sistema mono processore due thread funzionano così:

220px-Multithreaded_process.svg.png

220px-Multithreaded_process.svg.png

( immagine presa da Wikipedia )

Il thread ha 4 stati definiti

  • Creazione
  • Blocco
  • Sblocco
  • Terminazione

Lo stato di creazione e di terminazione non necessitano di particolari spiegazioni. Gli stati di Blocco e Sblocco sono invece più complessi perché sono un po’ il cuore del thread. Vengono gestiti da strutture dati che in gergo si chiamano semafori e che sono associati agli eventi di sistema. Tipicamente, possono essere di due tipi:

  • asincroni
  • sincroni

Quelli asincroni sono eventi non predicibili, quelli sincroni invece sono tipicamente associati ad un timer e quindi avvengono in un tempo noto.
Un thread, ricorda molto la features degli interrupt nei microcontrollori più complessi perché hanno la stessa tipologia degli eventi di sistema. Dopo questo stringato excursus sui thread veniamo al nostro software. Diciamo che nonostante il software soffrisse di questa Filariasi linfatica cronica, tutte le installazioni fino a quel tempo non avevano dato grossi problemi.

Il vero problema nasceva dal fatto che saltuariamente il programma andava in crash con una frequenza, però, talmente bassa, da rendere particolarmente difficile le operazioni di debug. Nell'ultima installazione le cose andarono molto diversamente, il crash era sistematico e quotidiano. La frequenza era tale che il softwareista poteva verificarlo direttamente. Benissimo !

I centri di raccolta dati hanno dei sistemi hardware un po' particolari. Le installazioni si basano tutte su una piattaforma che ha alla base un ambiente definito con il termine tecnico di macchina virtuale. Tipicamente i desktop di casa, come quello che usiamo tutti noi, sono monolitici; intendo dire che ad una unica base hardware, corrisponde un unico sistema operativo che si interfaccia con l’utente. Alcune case come la VMWare hanno sviluppato complessi software di virtualizzazione di macchine e reti.
Semplificando molto, questi software permettono appunto di creare più istanze di interfaccia utente, cioè ad un unica base hardware puoi avere più sistemi operativi che possono essere utilizzati da più utenti.

I thread implementati erano diversi, ma per essere sicuri che questi non interagissero maleficamente fra di loro, era stata inserita una gestione a semafori in modo tale che, girassero solo due thread alla volta: quello della dialog principale ( sempre ), e uno ( e solo uno ) degli altri thread disponibili. Ora il softwareista con un colpo d’occhio notò che la macchina virtuale prevedeva l’implementazione di due processori di tipo Xeon.

Gli Xeon sono storicamente la variante più ricca dei processori Pentium erano quelli diciamo utilizzati dai professionisti e da chi aveva le palanche... . L’amministratore di rete a seguito delle nostre perplessità ci disse pacifico.
“Si certo...i due Xeon li ho configurati io. Fanno parte delle impostazioni di virtualizzazione della macchina, se volevo ne potevo mettere anche 4 di processori... ma due mi sembravano sovrabbondanti ”

Il sospetto era che sin’ora tutte le installazioni era state fatte su PC da quattro soldi che sono di fatto mono processore. In questo caso, l’implementazione dei due processori era vera ( anche se virtuale ) e il VMWare stava funzionando alla grande. I thread dell’applicativo in questione sulla macchina giravano d’avvero contemporaneamente e questo rendeva i crash da saltuari a sistematici. In pratica il softwareista pensò che ci fosse un problema di Mutex fra i thread.

Su wikipedia da grandi inconsapevoli fetecchie alla voce thread scrivono con grande solerzia:

La programmazione con diversi thread ha 
reputazione di essere una tecnica abbastanza 
difficile. In realtà, usare un thread non comporta 
particolari difficoltà di per sé: la difficoltà consiste
usualmente nel sincronizzare questi diversi thread,
perché non è mai possibile sapere, al momento della 
programmazione, a che punto dell'esecuzione sarà
un thread specifico: la loro progressione dipende infatti 
dalle priorità decise dal sistema operativo. In particolare 
la caratteristica tipica dei thread di condividere risorse 
tra loro, come appunto la sezione di dati, può portare 
ad alcuni problemi. Più thread infatti possono accedere 
ad una stessa variabile e modificarne il valore.
Sebbene questo non accada nello stesso momento, perché l'accesso ad una variabile, che di fatto è memorizzata in memoria RAM, è intrinsecamente limitata ad un'unità al massimo, può accadere che un thread modifichi il valore di una variabile, mentre un altro thread necessita del vecchio valore memorizzato in essa. Si ricorre pertanto all'uso di tecniche di sincronizzazione come la mutua esclusione per risolvere il problema. Ne consegue che, idealmente, un thread dovrebbe eseguire del codice quanto più possibile indipendente dal resto del programma. Inoltre, gli errori nella sincronizzazione tra thread sono spesso molto difficili da individuare, perché la loro occorrenza dipende essenzialmente dall'ambiente in cui il programma viene eseguito. La sincronizzazione di un thread con un altro è normalmente necessaria per permettere a questi di comunicare tra di loro e di restituire i risultati di una funzione al processo principale; essa viene normalmente realizzata tramite mutex.
( wikipedia )

Come si può notare, il problema della condivisione delle risorse fra thread è una cosa abbastanza nota nell'ambiente, tanto che mamma Microsoft, per ovviare ai problemi di sincronizzazione, un round tips lo aveva già implementato nella notte dei tempi chiamandolo

Critical Section ( d’ora in avanti CS )

quella che chiamano Mutex e cioè la mutua esclusione dei thread, deve avvenire seguendo una serie di precise condizioni che riprendo sempre da wikipedia...

  • un solo processo o thread accede alla regione critica;
  • nessun processo può bloccarsi in sezione critica
  • evitare deadlock e starvation
  • nessuna assunzione sulla velocità dei processi
  • nessun processo fuori dalla sezione critica può impedire ad un altro di entrare
  • accesso alla sezione critica consentito in un tempo definito.

(wikipedia)

Nel punto tre, quando dicono di evitare che accadano altri devastanti bachi come il deadlock o lo starvation, si potrebbe rispondere con altri pesanti intercalari, ma siccome abbiamo imparato ad essere dei signori, evitiamo le provocazioni. Riprendiamo invece la CS e la sua implementazione. Nel costruttore dell’oggetto dichiariamo l’inizializzazione

Class::TestClass(void)
{

InitializeCriticalSection (&m_criticalSection);

}

Nel distruttore invece la disabilitiamo

Class::~TestClass(void)
{

DeleteCriticalSection(&m_criticalSection);

}

Le sezioni di codice da proteggere devono quindi essere scritte così:

EnterCriticalSection (&m_criticalSection);
AddItem(p);
LeaveCriticalSection (&m_criticalSection);

Per associazione con i microprocessori la CS ricorda molto le istruzioni CLI e SEI di alcuni microcontrollori ( Atmel su tutti ) che abilitano e disabilitano gli interrupt globali. Spesso vengono utilizzati appunto in contesti simili e cioè quando abbiamo sezioni di codice che gestiscono parti critiche che non possono essere interrotte da nessuno.

Il crash svanì d’incanto e come per magia il softwareista si risollevò dalla pressione continua che quel baco aveva causato da tempo. Quella sera i suoi colleghi lo salutarono e lui rimase per un momento interdetto ma quella volta diversamente dalle altre alzò la testa, allungò il dito sul tasto di on/off del computer spegnendolo e nello stesso tempo disse “aspettatemi … esco con voi”.

5

Commenti e note

Inserisci un commento

di ,

ciao paolino... grazie per il passaggio ;) magari un giorno...

Rispondi

di ,

Bello! Mi mancano un po' i tuoi racconti di vita vissuta, ma non dispero: magari la seconda o la terza parte ti vedranno coinvolto nello stanare il maledetto bug :-) Grazie.

Rispondi

di ,

ciao carlo... infinitamente grato per i complimenti e lietissimo di averti tenuto compagnia per qualche minuto, grazie per il passaggio. alla prossima nextime ciao... grazie per il passaggio. Diciamo che, in verità, qualche volta mi concedo delle licenze discutibili, nel caso specifico però le cose citate da te sono un po' diverse rispetto a quelle effettivamente scritte nel post, alla prossima... ops nextime ;)

Rispondi

di ,

E' sabato mattina, al piano di sopra dormono ancora tutti. Una doccia veloce e ti siedi comodo in poltrona con un caffè nero bollente e un pad per leggere in pace il giornale prima che i bimbi ti assalgano. Uno sguardo veloce al Forum ed eccolo li, in prima pagina, Kirkegaard ti ha fatto un regalo questo week end ... letto tutto in un fiato con la paura di essere interrotto sul più bello dalla prole, bellissimo. Il maestro non si smentisce mai, grazie Kirkegaard; veramente un bel regalo. E il giornale? Beh, pazienza quello lo leggerò più tardi. ;-) -carlo.

Rispondi

di ,

Eppero' dire che VI non e' serio... e che c++ e' obsoleto... mica sono cose vere! Io lavoro professionalmente tutti i giorni con VI(m) e con c++ ( e no, c# NON lo uso del tutto nemmeno sui desktop, visto che non lavoro su macchine microsoft! )

Rispondi

Inserisci un commento

Per inserire commenti è necessario iscriversi ad ElectroYou. Se sei già iscritto, effettua il login.