Ghid pentru Raportarea Bug-urilor în Gentoo Chris White Shyam Mani Lucian Constantin Acest document indică modalitatea de raportare a bug-urilor utilizând Bugzilla. 1.5 2005-08-29 Introducere
Prefaţă

Unul din factorii care întârzie repararea unei probleme este modul în care aceasta este raportată. Prin crearea acestui ghid, sperăm să îmbunătăţim comunicarea dintre developer şi utilizator. Repararea problemelor raportate de utilizatori este o componentă foarte importantă, dacă nu crucială, a calităţii unui proiect, şi sperăm să devină un succes.

Bugs!!!!

În timp ce rulaţi comanda emerge sau în timp ce rulaţi un program şi ceea ce n-ar trebui să se întâmple se întâmplă -- aţi găsit un bug! Bug-urile vin în diferite forme, cum ar fi probleme de emerge sau segmentation faults. Indiferent care este cauza, o asemenea problemă trebuie rezolvată. Câteva exemple de bug-uri:

$ ./bad_code `perl -e 'print Ax100'`
Segmentation fault
/usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/backward/backward_warning.h:32:2:
warning: #warning This file includes at least one deprecated or antiquated
header. Please consider using one of the 32 headers found in section 17.4.1.2 of
the C++ standard. Examples include substituting the <X> header for the <X.h>
header for C++ includes, or <sstream> instead of the deprecated header
<strstream.h>. To disable this warning use -Wno-deprecated.
In file included from main.cc:40:
menudef.h:55: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:62: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:70: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:78: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
main.cc: In member function `void OXMain::DoOpen()':
main.cc:323: warning: unused variable `FILE*fp'
main.cc: In member function `void OXMain::DoSave(char*)':
main.cc:337: warning: unused variable `FILE*fp'
make[1]: *** [main.o] Error 1
make[1]: Leaving directory
`/var/tmp/portage/xclass-0.7.4/work/xclass-0.7.4/example-app'
make: *** [shared] Error 2

!!! ERROR: x11-libs/xclass-0.7.4 failed.
!!! Function src_compile, Line 29, Exitcode 2
!!! 'emake shared' failed

Aceste probleme sunt foarte neplăcute. Ce trebuie să faceţi odată ce au fost detectate? Următoarele secţiuni descriu două unelte importante folosite în repararea erorilor descoperite în timpul rulării programelor. Apoi, vom arunca o privire la erorile de compilare. Să începem cu prima unealtă de depanare a problemelor de rulare -- gdb.

Depanare folosind GDB
Introducere

GDB, sau (G)NU (D)e(B)ugger, este un program folosit pentru diacnosticarea problemelor de corupţie de memorie. Mai întâi, să vedem în ce constă procesul de depanare. Primul lucru care trebuie făcut este să emerge programul cu FEATURES="nostrip". Aceasta, va împiedica eliminarea simbolurilor de depanare din executabil. De ce se elimină această informaţie în mod uzual? Din acelaşi motiv pentru care paginile de manual sunt păstrate de sistem în formă compresată -- salvare de spaţiu pe hard disc. Iată un exemplu de executabil cu şi fără simboluri de depanare.

(fără simboluri de depanare)
-rwxr-xr-x  1 chris users 3140  6/28 13:11 bad_code
(cu simboluri de depanare)
-rwxr-xr-x  1 chris users 6374  6/28 13:10 bad_code

Pentru referinţă, bad_code este programul pe care îl vom depana folosind gdb mai târziu. După cum se vede, programul fără simboluri debug are o mărime de 3140 bytes, în timp ce programul cu simboluri are 6374 bytes, adică aproape dublu! Două alte lucruri pot fi făcute pentru a uşura depanarea. Primul este adăugarea ggdb3 la CFLAGS şi CXXFLAGS. Acest indicator adaugă mai multă informaţie debug decât în mod normal. Vom vedea mai târziu ce înseamnă aceasta. Iată cum ar putea arăta fişierul /etc/make.conf cu noii indicatori adăugaţi.

CFLAGS="-O1 -pipe -g -ggdb"
CXXFLAGS="${CFLAGS}"

Apoi, puteţi adăuga debug între indicatorii USE corespunzători pachetului respectiv. Aceasta se poate face modificând fişierul package.use.

# echo "category/package debug" >> /etc/portage/package.use
Dacă directorul /etc/portage nu există implicit, va trebui să fie creat, dacă un aţi făcut-o deja. Dacă pachetul are deja indicatori USE setaţi în package.use, va trebui să modificaţi fişierul într-un editor de text.

Apoi reinstalaţi pachetul cu modificările de mai sus după cum se arată mai jos.

# FEATURES="nostrip" emerge pachet

Acum, că simbolurile sunt incluse, putem începe operaţia de depanare.

Rularea programului folosind GDB

Să presupunem că avem un program numit "bad_code". Cineva susţine că programul returnează eroare şi ne dă un exemplu. Începem testarea:

$ ./bad_code `perl -e 'print Ax100'`
Segmentation fault

Se pare că utilizatorul a avut dreptate, acesta este în mod clar un bug. A venit timpul să ne folosim de gdb pentru a diagnostica această problemă. Pentru început rulăm gdb cu --args, apoi îi dăm întregul program cu argumentele descrise mai jos:

$ gdb --args ./bad_code `perl -e 'print Ax100'`
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
Putem de asemenea să folosim "core dumps". Aceste fişiere conţin aceeaşi informaţie care este produsă de gdb. Pentru depanarea bad_code folosind un fişier core va trebui să rulaţi gdb ./bad_code core unde core este numele fişierului core.

Ar trebui să vedeţi un prompt intitulat "(gdb)" care aşteaptă comenzi. Mai întâi pornim programul. Introducem run drept comandă de prompt şi primim înapoi ceva de genul:

(gdb) run
Starting program: /home/chris/bad_code

Program received signal SIGSEGV, Segmentation fault.
0xb7ec6dc0 in strcpy () from /lib/libc.so.6

Vedem aici programul pornind şi primind notificarea SIGSEGV sau Segmentation Fault. Acesta este GDB spunându-ne că programul a eşuat. De asemenea, ne spune care a fost ultima funcţie care a rulat înainte de crash. Totuşi, informaţia nu este teribil de folositoare, există nenumărate locuri în program unde funcţia strcpy este chemată, şi este dificil de determinat care din ele a generat problema. Pentru a ajuta pe developer trebuie să generăm ceea ce se numeşte un backtrace. Un backtrace este o listă a funcţiilor care au fost executate în succesiune de program, terminând cu funcţia care a generat crash-ul. Funcţiile care au fost returnate fără crash nu apar în backtrace. Pentru a genera backtrace-ul, introduceţi comanda bt în promptul gdb. Veţi obţine ceva de genul:

(gdb) bt
#0  0xb7ec6dc0 in strcpy () from /lib/libc.so.6
#1  0x0804838c in run_it ()
#2  0x080483ba in main ()

Backtrace-ul ne spune că funcţia main() a fost chemată prima, urmată de funcţia run_it(), iar undeva în această funcţie se găseşte apelul funcţiei strcpy() care a generat problema. Există un număr mic de excepţii când un backtrace nu ne oferă informaţia pe care o căutăm. Primul este cazul în care uităm să adăugăm simboluri de depanare cu FEATURES="nostrip". În acest caz, backtrace-ul arată în felul următor:

(gdb) bt
#0  0xb7e2cdc0 in strcpy () from /lib/libc.so.6
#1  0x0804838c in ?? ()
#2  0xbfd19510 in ?? ()
#3  0x00000000 in ?? ()
#4  0x00000000 in ?? ()
#5  0xb7eef148 in libgcc_s_personality () from /lib/libc.so.6
#6  0x080482ed in ?? ()
#7  0x080495b0 in ?? ()
#8  0xbfd19528 in ?? ()
#9  0xb7dd73b8 in __guard_setup () from /lib/libc.so.6
#10 0xb7dd742d in __guard_setup () from /lib/libc.so.6
#11 0x00000006 in ?? ()
#12 0xbfd19548 in ?? ()
#13 0x080483ba in ?? ()
#14 0x00000000 in ?? ()
#15 0x00000000 in ?? ()
#16 0xb7deebcc in __new_exitfn () from /lib/libc.so.6
#17 0x00000000 in ?? ()
#18 0xbfd19560 in ?? ()
#19 0xb7ef017c in nullserv () from /lib/libc.so.6
#20 0xb7dd6f37 in __libc_start_main () from /lib/libc.so.6
#21 0x00000001 in ?? ()
#22 0xbfd195d4 in ?? ()
#23 0xbfd195dc in ?? ()
#24 0x08048201 in ?? ()

Acest backtrace conţine un număr mare de ??, deoarece fără simboluri de depanare, gdb nu ştie cum a fost rulat programul. De aceea este esenţial să avem simboluri de depanare în executabil. Mai devreme am menţionat indicatorul -ggdb. Să vedem cum arată backtrace-ul nostru cu acest indicator activ:

(gdb) bt
#0  0xb7e4bdc0 in strcpy () from /lib/libc.so.6
#1  0x0804838c in run_it (input=0x0) at bad_code.c:7
#2  0x080483ba in main (argc=1, argv=0xbfd3a434) at bad_code.c:12

Mult mai multă informaţie este disponibilă în acest caz. Nu numai numele funcţiei dar şi numărul liniei de cod sursă este disponibil. Aceasta este metoda preferată, preţul plătit este o creştere a dimensiunilor executabilului. Iată cum variază această dimensiune pentru un program cu sau fără simboluri de depanare, şi cu indicatorul -ggdb activ:

(fără simboluri de depanare)
-rwxr-xr-x  1 chris users 3140  6/28 13:11 bad_code
(cu simboluri de depanare)
-rwxr-xr-x  1 chris users 6374  6/28 13:10 bad_code
(idicatorul -ggdb activ)
-rwxr-xr-x  1 chris users 19552  6/28 13:11 bad_code

După cum se vede, -ggdb adaugă 13178 octeţi la executabil comparat cu versiunea cu simboluri de depanare însă -ggdb inactiv. Această creştere în dimensiune poate fi esenţială când informaţia este prezentată dezvoltatorilor. Backtrace-ul poate fi salvat într-un fişier text prin copy şi paste din terminal (dacă este un terminal non-x puteţi folosi gpm. Pentru a simplifica acest document, recomand să consultaţi documentaţia gpm). După ce terminăm cu gdb, putem ieşi din acest program.

(gdb) quit
The program is running. Exit anyway? (y or n) y
$

Aceasta încheie demonstraţia noastră de gdb. Folosind gdb sperăm că veţi crea rapoarte de bug-uri mai bune. Există totuşi alte tipuri de probleme care pot rezulta într-o eroare a programului, de exemplu acces impropriu de fişiere. Pentru a diagnostica o asemenea problemă folosim programul utilitar strace.

Diagnosticarea problemelor de acces de fişiere folosind strace
Introducere

Deseori, programele folosesc alte fişiere pentru a obţine informaţia de configuraţie, pentru a accesa informaţille hardware sau pentru a scrie jurnalele. Uneori, programele încearcă să acceseze aceste fişiere în mod incorect. Pentru a diagnostica astfel de probleme se foloseşte utilitarul strace. Acest utilitar trasează toate apelurile de sistem (de aici şi numele) care includ toate accesele la memorie şi fişiere. Luăm ca exemplu un program numit foobar. În timpul trecerii la foobar2 observăm că toată informaţia de configurare lipseşte! Foobar versiunea 1 utilizează configuraţia din "foo" în timp ce foobar2 caută configuraţia în "bar".

$ ./foobar2
Configuration says: bar

Versiunea originală folosea configuraţia setată în foo, deci să încercăm strace să vedem ce se întâmplă.

Folosirea strace pentru a investiga problema

Folosim strace pentru a obţine o listă a call-urilor sistem. Pentru aceasta rulăm strace cu argumentul -o[file]. Să încercăm astfel pentru foobar2.

# strace -ostrace.log ./foobar2

Această comandă crează un fişier intitulat strace.log în directorul curent. Verificăm fişierul, părţile relevante sunt descrise mai jos.

open(".foobar2/config", O_RDONLY)       = 3
read(3, "bar", 3)                       = 3

Aha! Deci aceasta era problema. Cineva a modificat numele directorului de configurare din .foobar în .foobar2. De asemenea, programul citeşte fişierul "bar" după cum trebuie. În acest caz recomandăm ca maintainer-ul ebuild-ului să afişeze un avertisment. Temporar pentru a ne rezolva problema, putem copia configuraţia din .foobar şi o putem modifica pentru a obţine rezultate corecte.

Concluzii

În acest mod sunt diagnosticate problemele de rulare a programelor. Aceste probleme devin vizibile numai în cazul în care programul este rulat. În unele cazuri nu ajungem atât de departe, s-ar putea ca programul nici să nu compileze. Să vedem cum se diagnostichează problemele de compilare rezultate la emerge.

Diagnosticarea problemelor emerge
Introducere

Erorile emerge sunt un caz major de frustrare pentru utilizatori. Raportarea lor este crucială pentru Gentoo. Să aruncăm o privire la un ebuild intitulat foobar2 care conţine erori de compilare.

Diagnosticarea erorilor emerge

Presupunem următoarea eroare emerge simplă:

gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2-7.o foobar2-7.c
gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2-8.o foobar2-8.c
gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2-9.o foobar2-9.c
gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2.o foobar2.c
foobar2.c:1:17: ogg.h: No such file or directory
make: *** [foobar2.o] Error 1

!!! ERROR: sys-apps/foobar2-1.0 failed.
!!! Function src_compile, Line 19, Exitcode 2
!!! Make failed!
!!! If you need support, post the topmost build error, NOT this status message

Toate merg bine până când compilarea se opreşte brusc cu un mesaj de eroare. Această eroare particulară poate fi împărţită în trei secţiuni: mesajul de compilare, eroarea de build şi eroarea de emerge după cum se arată mai jos.

(Mesaje de compilare)
gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2-7.o foobar2-7.c
gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2-8.o foobar2-8.c
gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2-9.o foobar2-9.c
gcc -D__TEST__ -D__GNU__ -D__LINUX__ -L/usr/lib -I/usr/include -L/usr/lib/nspr/ -I/usr/include/fmod   -c -o foobar2.o foobar2.c

(Eroare build)
foobar2.c:1:17: ogg.h: No such file or directory
make: *** [foobar2.o] Error 1

(Eroare emerge)
!!! ERROR: sys-apps/foobar2-1.0 failed.
!!! Function src_compile, Line 19, Exitcode 2
!!! Make failed!
!!! If you need support, post the topmost build error, NOT this status message

Mesajele de compilare stau la baza erorii. În general, este bine să includem cel puţin 10 linii cu informaţie de compilare, pentru a-l informa pe developer unde exact se afla compilarea.

Erorile de build (sau erori de make) sunt erorile în sine, şi este ceea ce developer-ul are nevoie. Când vedeţi "make: ***", acesta este în general locul în care eroarea s-a produs. În general puteţi copy şi paste 10 linii deasupra erorii make iar dezvoltatorul va putea rezolva problema. În cazul în care aceasta nu este suficient, vom vedea ulterior o alternativă.

Eroarea emerge este generată de utilitarul emerge. Adeseori, utilizatorii fac greşeala să trimită dezvoltatorului numai această informaţie. În sine, această informaţie singură este total irelevantă pentru dezvoltator, însă împreună cu eroarea de compilare şi cea de build îi spune acestuia ce aplicaţie şi ce versiune a pachetului are problema. Ca o notă separată, make nu este întodeauna folosit în procesul de build. Dacă nu puteţi găsi eroarea "make: ***", copy şi paste 20 de linii înainte de mesajul de eroare. Aceasta va fi suficient în majoritatea cazurilor. Să presupunem că eroarea este deosebit de mare şi 10 linii nu sunt suficiente. În acest caz ne folosim de PORT_LOGDIR.

emerge şi PORT_LOGDIR

PORT_LOGDIR este o variabilă portage care setează directorul de log pentru emerge. Să aruncăm o privire să vedem ce înseamnă aceasta. Mai întâi, rulaţi emerge setând PORT_LOGDIR pentru locaţia dumneavostră favorită. Să presupunem că dorim să o setăm ca /var/log/portage.

Implicit, această locaţie nu există şi va trebui să o creem. Dacă nu, portage nu va fi capabil să scrie log-urile.
# PORT_LOGDIR=/var/log/portage emerge foobar2

Acum, emerge va eşua din nou. Totuşi, în acest caz avem un log cu care putem lucra. Îl putem ataşa la raport de bug ulterior. Să aruncăm o privire în directorul de log.

# ls -la /var/log/portage
total 16
drwxrws---   2 root root 4096 Jun 30 10:08 .
drwxr-xr-x  15 root root 4096 Jun 30 10:08 ..
-rw-r--r--   1 root root 7390 Jun 30 10:09 2115-foobar2-1.0.log

Formatul fişierului log este [contor]-[nume pachet]-[versiune].log. Counter este o variabilă specială al cărui scop este de a număra global pachetele care au fost emerged. Această variabilă are scopul de a preveni duplicarea jurnalelor de emerge. O scurtă privire în acest fişiere ne va arăta întregul proces de emerge. Acest fişier va fi ataşat mai târziu la raport după cum se descrie în secţiunea referitoare la raportarea bug-ului. Înainte de a continua mai departe, să vedem cum se face o căutare pentru bug-uri deja raportate.

Utilizarea Bugzilla pentru a căuta bug-uri raportate deja
Introducere

Gentoo foloseşte Bugzilla pentru gestionarea bug-urilor. Bugzilla poate fi accesată prin HTTPS şi HTTP. Folosiţi un protocol sau altul în funcţie de gradul de securitate al reţelei sau de gradul de paranoia :). Pentru consistenţă vom folosi versiunea HTTPS în exemplele care urmează. Mergeţi la Gentoo Bugs pentru a vedea cum arată.

Una dintre cele mai neplăcute activităţi pentru dezvoltatori este găsirea bag-urilor duplicate. Aceasta rezultă în irosirea unei cantităţi impresionante de timp care ar putea fi utilizat altfel pentru repararea propriu-zisă a problemei. Deseori, această situaţie poate fi prevenită printr-un simplu search. Explicăm în continuare cum să căutăm dacă există deja un bug similar în baza de date. Folosim de exemplu eroarea emerge xclass folosită anterior.

/usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/backward/backward_warning.h:32:2:
warning: #warning This file includes at least one deprecated or antiquated
header. Please consider using one of the 32 headers found in section 17.4.1.2 of
the C++ standard. Examples include substituting the <X> header for the <X.h>
header for C++ includes, or <sstream> instead of the deprecated header
<strstream.h>. To disable this warning use -Wno-deprecated.
In file included from main.cc:40:
menudef.h:55: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:62: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:70: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:78: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
main.cc: In member function `void OXMain::DoOpen()':
main.cc:323: warning: unused variable `FILE*fp'
main.cc: In member function `void OXMain::DoSave(char*)':
main.cc:337: warning: unused variable `FILE*fp'
make[1]: *** [main.o] Error 1
make[1]: Leaving directory
`/var/tmp/portage/xclass-0.7.4/work/xclass-0.7.4/example-app'
make: *** [shared] Error 2

!!! ERROR: x11-libs/xclass-0.7.4 failed.
!!! Function src_compile, Line 29, Exitcode 2
!!! 'emake shared' failed

Începem căutarea la Pagina de Start Bugzilla.

Click pe "Query Existing bug reports". Motivul pentru care folosim aceasta în loc de o căutare simplu, este că o căutare simplă tinde să dea rezultate vagi şi, în general, crează probleme utilizatorilor în găsirea bug-urilor duplicate. După click suntem direcţionaţi la următoarea pagină.

Dacă aţi mai folosit Advanced Search, veţi vedea probabil acea pagină.

Continuaţi prin a apăsa pe "Advanced Search" pentru a ajunge la pagina de Căutare Avansată.

Pagina de Căutare Avansată arată ca mai sus. Deşi pare complicată, ne vom uita la un număr mic de opţiuni pentru a filtra rezultatele.

În primul câmp intitulat Summary vom pune numele pachetului cu probleme. Dacă Bugzilla nu returnează nici un rezultat încercaţi fără a specifica numele pachetului, asta pentru cazurile în care bug-ul nu a fost raportat utilizând acest nume (foarte puţin probabil însă s-au văzut cazuri).

Product, Component, şi Version sunt lăsate la valoarea implicită pentru a nu fi excesiv de specific în cazul în care bug-ul a fost introdus pentru o altă versiune/componentă/etc.

Comment este cel mai important câmp. Folosiţi-l pentru a detalia problema specifică. Practic, nu folosiţi nimic de la începutul erorii de build, folosiţi o linie de dinaintea ei care menţionează eroarea. De asemenea, înlăturaţi orice punctuaţie pentru a împiedica Bugzilla să interpreteze rezultatele în mod greşit. Exemplu din eroarea emerge xclass:

menudef.h:78: error: brace-enclosed initializer used to initialize `OXPopupMenu'
(eliminaţi caractele apostrof ' ')
menudef.h 78 error brace-enclosed initializer used to initialize OXPopupMenu

Conţinutul de mai sus este destul de specific pentru a găsi bug-ul, fără a intra în alte probleme de compilare ale xclass.

URI, Whiteboard şi Keywoards pot fi lăsate nemodificate. Tot ce am introdus până acum ar trebui să fie suficient să găsim bug-ul. Să vedem ce am introdus.

Apăsăm apoi pe butonul Search şi primim rezultatele...

Numai două bug-uri! Aceasta este mult mai uşor de verificat. Click pe primul, şi bineînţeles este ceea ce căutam.

Nu numai că l-am găsit, însă a şi fost rezolvat. Verificând ultimul comentariu, acesta este soluţia pentru bug şi ştim ce trebuie să facem pentru a-l rezolva. Să vedem acum ce s-ar fi întâmplat dacă nu am fi apelat la Căutare Avansată.

Încă patru bug-uri. Pentru pachete mai mari situaţia este şi mai rea. Totuşi, folosind aceste unelte simple, putem filtra suficient de bine lista de bug-uri pentru a-l localiza.

Concluzii

Să presupunem că aţi căutat şi căutat şi nu aţi găsit nimic. În acest caz aveţi un bug nou. Să vedem cum arată procesul de raportare a bug-urilor noi.

Reportarea bug-urilor
Introducere

În acest capitol vom descrie modul de utilizare Bugzilla pentru a raporta un bug nou. Începeţi prin a merge la Gentoo Bugs şi ...

Click pe "Report a Bug - Using the guided format"

După cum vedeţi accentul major se pune pe introducerea bug-ului în locul corespunzător. Majoritatea bug-urilor merg la Gentoo Linux.

În ciuda acestui fapt, unii utilizatori vor raporta bug-ul către portage development (presupunerea este că echipa de dezvoltatori portage este responsabilă de structura portage) sau infra (prespunerea este că infra are acces la mirror-uri şi rsync şi poate să rezolve problema în mod direct). Lucrurile nu stau aşa.

O altă neînţelegere se referă la bug-urile pentru documentaţie. De exemplu, un utilizator găseşte un bug pe pagina de Documentaţie Catalyst. Tendinţa este să se posteze un bug sub Docs-user care va fi trimis apoi la GDP (Proiectul de Documentaţie Gentoo), în loc de Release Engineering. De regulă, numai documentaţia din http://www.gentoo.org/doc/* este pentru GDP. Orice document în http://www.gentoo.org/proj/* aparţine echipei respective.

Am prefera să avem un bug care nu aparţine echipei Gentoo Linux decât să avem un bug Gentoo Linux trimis altundeva. Nici una dintre variante nu este bună, însă primul caz este acceptat şi înţeles (cu excepţia bug-urilor referitoare la website.. ar putea să fie o problemă cu acesta...).

Bug-ul nostru va fi postat în Gentoo Linux întrucât este o problemă de ebuild. Ne ducem acolo şi începem primul pas al procesului...

Primul pas este foarte important, după cum este sugerat şi de textul în roşu. Acesta este locul unde căutaţi dacă altcineva nu are aceeaşi problemă. Dacă săriţi peste acest pas şi un bug similar este găsit, va fi marcat ca DUPLICATE (Duplicat) în detrimentul timpului pierdut de echipa QA pentru această operaţie. Pentru a vă da o idee, bug-urile de mai sus sunt marcate drept duplicate. Trecem la pasul al doilea unde introducem mai multă informaţie.

Informaţie necesară

Să vedem despre ce este vorba.

  • În primul rând este Product. Specificând produsul, bug-ul va fi pus într-o categorie specifică a Bugzilla (pentru bug-uri gentoo.org), Docs-user (pentru documentaţie) sau Gentoo Linux (pentru ebuild-uri).
  • Component specifică unde se manifestă problema, mai specific în care parte a produsului problema a fost observată. Aceasta face clasificare bug-ului mai uşoară.
  • Hardware platform se referă la ce arhitectură rulaţi. Dacă rulaţi să spunem SPARC, va trebui să setaţi SPARC.
  • Operating System se referă la sistemul de operare pe care îl folosiţi. Gentoo este o "Meta-distribuţie", şi poate rula şi alte sisteme de operare pe lângă Linux.

Deci, pentru exemplul nostru avem:

  • Product - Gentoo Linux (deoarece este o problemă ebuild)
  • Component - Application (este o problemă cu aplicaţia foobar2)
  • Hardware Platform - All (Această problemă poate apare pe mai multe arhitecturi)
  • Operating System - All (Poate fi întâlnită pe toate tipurile de sistem)
  • Build Identifier este variabila User Agent a browser-ului pe care îl folosiţi pentru a raporta bug-ul (în scopuri de jurnalizare). Poate fi lăsat neschimbat.
  • URL este opţional, şi poate fi folosit pentru a specifica o pagină web unde sunt depozitate erorile (pastebin, etc). Motivul pentru care această informaţie are valoare pentru dezvoltatori este că poate fi folosită ca referinţă şi este de preferat.
  • În Summary trebuie să puneţi categoria pachetului, numele şi numărul.

A nu include categoria pachetului în Summary nu este rău, însă se recomandă. Dacă însă numele pachetului nu este inclus, este greu de spus la ce se referă bug-ul şi va trebui să vă întrebăm mai târziu. Numărul versiunii este important pentru toţi utilizatorii care caută prin lista de bug-uri. Dacă 20 de utilizatori au trimis bug-uri şi nici unul nu a specificat o versiune, este imposibil pentru cei ce vor căuta bug-uri mai târziu să spună dacă este sau nu un bug. În acest caz ar trebui să se uite pe rând la fiecare bug însă dacă sunt de exemplu 200 de bug-uri... nu este prea uşor. După informaţia referitoare la pachet trebuie să includeţi o mică descriere a incidentului. Iată un exemplu:

Aceste reguli simple vor uşura prelucrare ulterioară a bug-urilor. În continuare o serie de detalii. Vom lua un mic exemplu.

Cu aceasta dezvoltatorul ştie de ce trimitem bug-ul. Developer-ul va încerca să îl reproducă. Reproductibilitatea ne spune cât de des putem face ca problema să se întâmple din nou. În acest caz, o putem reproduce de fiecare dată rulând foobar2. Să adăugăm această informaţie.

Am explicat deci că am găsit un bug. Următorul pas este să explicăm ce rezultate am obţinut şi ce credem că ar fi trebuit să conţină.

Orice informaţie adiţională poate fi adăugată. Aceasta poate conţine stack traces, jurnalul comenzii strace, secţiuni (deoarece întregul log este foarte mare şi nu foarte folositor), şi cel mai important rezultatul lui emerge --info pe sistemul dumneavoastră. Un exemplu:

Apoi selectăm severitatea bug-ului. Puţină atenţie este necesară. În cele mai multe cazuri este OK să o lăsăm aşa cum este şi altcineva o va mări sau micşora de la caz la caz. Dacă totuşi decideţi să măriţi severitatea, vă rugăm să citiţi cu atenţie ca să nu faceţi o greşeală. O explicaţie a nivelelor de severitate o găsiţi mai jos.

  • Blocker - Programul nu vrea să se compileze sau crează probleme în sistem. De exemplu pachetul baselayout va împiedica boot-area sistemului şi ar fi un candidat bun pentru nivelul blocker.
  • Critical - programul generează pierderi de date sau pierderi de memorie în timpul rulării. Din nou, un program important cum ar fi de exemplu net-toos care nu compilează poate fi introdus pe nivelul critical. Sistemul va porni, însă pachetul este esenţial pentru funcţionarea corespunzătoare a sistemului.
  • Major - Crash de program, însă nimic care să distrugă sistemul sau să pierdeţi informaţie.
  • Minor - Crash de program din când în când, cu posibile posibilităţi de ocolire.
  • Normal - default. Dacă nu sunteţi sigur lăsaţi bug-ul pe acest nivel. Dacă este un build nou sau o modificare cosmetică, citiţi mai jos.
  • Trivial - lucruri precum greşeli de ortografie sau spaţii libere de curăţat.
  • Enhancement - Cerere pentru a implementa o facilitate noua în program sau mai specific ebuild-uri noi.

Lăsăm nivelul neschimbat, pe Normal.

Trimitem bug-ul apăsând pe butonul Submit Bug Report. Verfificaţi Bug-ul 97561 pentru a vedea cum arată rezultatul. Am raportat bug-ul! Să vedem ce se întâmplă cu acesta în continuare.

Manipularea Bug-ului

Dacă ne uităm la bug, vedem informaţia pe care am trimis-o. Vom observa ca bug-ul a ajuns la bug-wranglers@gentoo.org. Aceasta este locaţia implicită pentru bug-urile componentei Application.

Detaliile introduse de dumneavoastră sunt de asemenea disponibile.

În general cei din echipa bug-wranglers nu vor rezolva bug-ul, acesta va fi trimis unui developer (puteţi cere bug-wranglers să vi-l trimită dumneavoastră). Pentru aceasta se foloseşte metadata.xml incorporată în pachet. O puteţi găsi uzual în /usr/portage/category/package/metadata.xml. De exemplu pentru pachetul nostru foobar2:

Trebuie să fiţi cel care a raportat bug-ul sau un membru al unui grup Gentoo Bugzilla specific (ca de exemplu Gentoo Developers) pentru a putea reatribui bug-ul.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<herd>chriswhite</herd>
<maintainer>
<email>chriswhite@gentoo.org</email>
<name>Chris White</name>
</maintainer>
<longdescription lang="en">
Foobar2 is a package that uses a configuration file to display a word.
</longdescription>
</pkgmetadata>

Observaţi secţiunea manitainer. Aceasta listează maintainer-ul pachetului, care în acest caz sunt eu, Chris White. Adresa de email listată este chriswhite@gentoo.org. Vom folosi aceasta pentru a reatribui bug-ul persoanei care trebuie. Click pe Reassign bug to, şi introduceţi adresa de email.

Un bug pentru un pachet fără metadata.xml trebuie reatribuit lui maintainer-needed@gentoo.org iar un pachet care are nevoie de un Gentoo Developer trebuie trimis la maintainer-wanted@gentoo.org.

Apăsaţi apoi butonul Commit pentru ca schimbarea să aibă loc. Bug-ul mi-a fost reatribuit mie. Puţin mai târziu, voi răspunde (de regulă prin email) la bug. Am spus că aş dori să văd un jurnal strace pentru a înţelege cum încearcă programul să ajungă la fişierele de configurare. Folosind instrucţiunile anterioare obţineţi un jurnal pe care îl ataşaţi bug-ului. Pentru aceasta apăsaţi "Create A New Attachement".

Acum, trebuie să ataşăm jurnalul. Haideţi să parcurgem toţi paşii.

  • File - Aceasta este locaţia fişierului pe calculatorul dumneavoastră. În acest exemplu locaţia este strace.log. Puteţi folosi butonul "Browse..." pentru a selecta fişierul, sau introduceţi locaţia direct ca text.
  • Description - O singură linie, cu puţine cuvinte descriind fişierul ataşat. Introducem starce.log şi se înţelege de la sine.
  • Content Type - Acesta este tipul fişierului ataşat la bug.
  • Obsoletes - Dacă alte fişiere au fost ataşate anterior, aveţi opţiunea să le declaraţi învechite. În cazul nostru, acesta fiind primul fişier ataşat, nu ne facem probleme.
  • Comment - Introduceţi orice comentariu referitor la fişier pe care îl consideraţi relevant, dacă este nevoie.

În ceea ce priveşte Content Type, iată câteva detalii. Puteţi bifa opţiunea "patch" dacă trimiteţi un patch. Altfel, puteţi cere interfeţei Bugzilla să autodetecteze tipul fişierului (nerecomandat). Cealaltă opţiune este "select form list", este cea mai frecvent folosită. Alegeţi text simplu (text/plain) pentru majoritatea fişierelor, cu excepţia fişierelor binare cum ar fi imagini (care pot fi image/gif, image/jpeg sau image/png) sau arhive compresate precum .tar.bz2 care folosesc tipul application/octet-stream.

Trimitem strace.log şi se reflectată în raport.

Am menţionat anterior că uneori ebuild-urile vă vor cere să ataşaţi un fişier în mesajul de eroare. Un exemplu este mai jos.

configure: error: PNG support requires ZLIB. Use --with-zlib-dir=<DIR>

!!! Please attach the config.log to your bug report:
!!! /var/tmp/portage/php-5.0.3-r1/work/php-5.0.3/config.log

!!! ERROR: dev-php/php-5.0.3-r1 failed.
!!! Function econf, Line 485, Exitcode 0
!!! econf failed
!!! If you need support, post the topmost build error, NOT this status message.

Vă rugăm să ataşaţi orice fişier menţionat în acest raport.

Să presupunem că în timp ce facem aceasta, o altă persoană găseşte bug-ul căutând prin bugzilla şi este curios să vadă ce se întâmplă cu bug-ul. Ar putea să facă aceasta intoducând adresa de email în câmpul Add CC după cum se arată mai jos. Puteţi în acest fel să urmăriţi orice bug prin această metodă.

Adresele de email trebuie să fie înregistrate cu Gentoo Bugzilla. În cazul când aveţi mai multe adrese, le introduceţi separate prin virgule sau spaţii.

După toată această muncă, bug-ul va trece prin diferite stagii. Aceasta se face în general de Dezvoltatorii Gentoo şi uneori de către cel ce a raportat bug-ul. Urmează stadiile variate prin care poate trece un bug în timpul valabilităţii acestuia.

  • UNCONFIRMED - Nu apare prea des. Aceasta înseamnă că cel care a raportat bug-ul folosind metoda avansată şi nu este sigur că acesta este un bug.
  • NEW - Prima oară când bug-ul este deschis, este considerat nou.
  • ASSIGNED - Când persoana căreia bug-ul i-a fost atribuit îl validează. Bug-ul este pus în acest stagiu în timp ce dezvoltatorul încearcă să înţeleagă care este problema. Acest stagiu ne informeză că bug-ul a fost acceptat şi este o problemă reală.
  • REOPENED - Cineva a rezolvat bug-ul iar soluţia nu pare să rezolve problema. În acest caz, puteţi redeschide bug-ul. Vă rugăm să nu abuzaţi această facilitate. Dacă dezvoltatorul închide bug-ul pentru a doua sau a treia oară, există şanse mari ca problema să fi fost rezolvată.
  • RESOLVED - O decizie fermă a fost luată cum că bug-ul ar fi fost rezolvat. De obicei bug-ul este pus în starea FIXED pentru a indica închiderea problemei, alte decizii sunt de asemenea posibile. Despre aceasta vom vedea mai târziu.
  • VERIFIED - Paşii prin care a trecut bug-ul sunt corecţi. Aceasta este ceva legat de QA.
  • CLOSED - Bug-ul a fost sfârşitul valabilităţii bug-ului, care este astfel "ingropat" între celelalte bug-uri.

Imediat apoi, găsim eroarea în strace log şi rezolvăm problema, trecând bug-ul în starea RESOLVED FIXED şi menţionând că a fost o schimbare în locaţia fişierelor de configurare. Un avertisment a fost introdus în ebuild. Problema a fost rezolvată şi veţi obţine:

Puţin mai jos veţi observa:

Aceasta vă permite să redeschideţi bug-ul dacă doriţi aşa ceva (de exemplu, developer-ul crede că l-a rezolvat, însă din punctul dumneavoastră de vedere problema persistă). Acum că a fost rezolvat, bug-ul poate fi pus în una din următoarele stări.

  • FIXED - Bug rezolvat, folosiţi instrucţiunile pentru a rezolva problema.
  • INVALID - Nu aţi efectuat o acţiune documentată special, care a cauzat bug-ul.
  • DUPLICATE - Nu aţi folosit corect acest ghid pentru a raporta bug-ul, şi avem o duplicare a lui.
  • WORKSFORME - Persoana însărcinată cu rezolvarea bug-ului nu îl poate reproduce.
  • CANTFIX - Uneori bug-ul nu poate fi rezolvat din anumite motive. Motivele for fi documentate de persoana însărcinată cu rezolvarea problemei.
  • WONTFIX - Se aplică în general la ebuild-uri noi sau cereri de îmbunătăţiri. Ne spune că dezvoltatorul nu vrea să adauge acestă facilitate deoarece nu este necesară, sau există o altă alternativă mai bună, sau nu poate fi rezolvată. Uneori puteţi sugera o soluţie pentru rezolvarea problemei.
  • UPSTREAM - Problema nu poate fi rezolvată de echipa de dezvoltatori Gentoo şi a fost trimisă dezvoltatoriloe care au scris original programul. Aceştia din urmă au diferite metode de comunicare. Acesta includ liste de discuţii, canale irc, sau chiar sisteme de raportare a bug-urilor. Dacă nu sunteţi sigur cum să îi contactaţi, puneţi o întrebare în bug şi cineva vă va direcţiona.

Uneori, înainte ca un bug să poată fi rezolvat, dezvoltatorul ar putea să vă ceară să încercaţi un ebuild de test. În capitolul următor vom vedea cum se face aceasta.

Testarea Ebuild-urilor
Preluarea Fişierelor

Să presupunem că aţi raportat un bug pentru foobar2. Problema de compilare a fost rezolvată de către dezvoltator, însă acesta ar avea nevoie de dumneavoastră să testaţi noul ebuild pentru a se asigura că funcţionează şi pentru dvs.:

Vocabularul este puţin confuz în acest caz. Pentru început, să vedem ce este un overlay. Un overlay este un director special precum /usr/portage, diferenţa fiind că în momentul când rulaţi emerge sync, fişierele conţinute în acesta nu vor fi şterse. Un director special /usr/local/portage a fost creat în acest scop. Continuăm prin a seta acest overlay în /etc/make.conf. Folosind un editor de text, adăugaţi următoarea linie undeva la sfârşitul fişierului.

PORTDIR_OVERLAY="/usr/local/portage"

Apoi, vom crea un nou director pentru acest ebuild de test. Vom pune noile fişiere în sys-apps/foobar2. Veţi observa al doilea comentariu care ne întreabă unde este directorul pentru acest patch. Noul director conţine informaţia de md5sum pentru versiunea particulară a pachetului şi orice alte fişiere care nu sunt incluse în mod normal în arhiva sursă (patch-uri, scripturi de iniţializare, etc). Acesta este un subdirector în pachet intitulat files. Continuaţi cu crearea acestor directoare:

# mkdir -p /usr/local/portage/sys-apps/foobar2/files
Opţiunea -p în comanda mkdir crează nu numai directorul files, dar şi cele care lipsesc (sys-apps şi foobar2 în acest caz).

Apoi descărcăm fişierele. ebuild este pus în /usr/local/portage/sys-apps/foobar2 iar apoi fişierul patch care este pus în /usr/local/portage/sys-apps/foobar2/files. În acest moment putem testa noul ebuild.

Testarea Noului Ebuild

Procesul de creare a unui ebuild care poate fi folosit de comanda emerge este foarte simplu. Acesta poate fi creat cu comanda ebuild. Rulaţi-o după cum se arată mai jos.

# ebuild foobar2-1.0.ebuild digest
>>> Generating digest file...
<<< foobar2-1.0.tar.bz2
>>> Generating manifest file...
<<< foobar2-1.0.ebuild
<<< files/digest-foobar2-1.0
<<< files/foobar2-1.0-Makefile.patch
>>> Computed message digests.

Să vedem dacă funcţionează corect.

# emerge -pv foobar2

These are the packages that I would merge, in order:

Calculating dependencies ...done!
[ebuild  N    ] sys-apps/foobar2-1.0  0 kB [1]

Total size of downloads: 0 kB
Portage overlays:
 [1] /usr/local/portage

Se pare că a mers! Veţi observa [1] lângă linia [ebuild]. Aceasta ne îndreaptă la /usr/local/portage, care este acel overlay pe care l-am creat anterior. Să rulăm comanda emerge.

# emerge foobar2
 Calculating dependencies ...done!
(liniile de compilare îndepărtate)
>>> Unpacking foobar2-1.0.tar.bz2 to /var/tmp/portage/foobar2-1.0/work
 * Applying foobar2-1.0-Makefile.patch ...                                    [ ok ]
(informaţiile despre compilare îndepărtate)
>>> Merging sys-apps/foobar2-1.0 to /
>>> chris +sandbox(preinst)
--- /usr/
--- /usr/bin/
>>> /usr/bin/foobar2

În prima secţiune, vedem că emerge a pornit în mod corespunzător. Din a doua secţiune deducem că noul patch a fost aplicat fără probleme din status-ul "[ ok ]". Noul patch funcţionează! În acest moment, putem să-l informăm pe dezvoltator că noul patch este bun, iar acesta îl poate comite în portage.

Concluzie

Încheiem astfel acest howto despre Bugzilla. Sperăm că îl veţi găsi folositor. Trimiteţi-mi orice întrebare, sugestie sau comentariu referitor la acest document pe adresa chriswhite@gentoo.org. Mulţumiri lui moreon pentru comentariile referitoare la flag-ul -g şi erorile de compilare, echipei #gentoo-bugs pentru ajutor cu bug-wrangling, Griffon26 pentru comentariile despre maintainer-needed, robbat2 pentru sugestiile general şi fox2mike pentru adăugirile şi corecturile aduse acestui document.