nastaveni timeoutu pro connect()

Pavel Kankovsky peak na argo.troja.mff.cuni.cz
Čtvrtek Duben 26 11:41:38 CEST 2001


On Thu, 26 Apr 2001, Ing. Pavel PaJaSoft Janousek wrote:

> > Jeste to jde udelat pres alarm()?
> 
> 	IMHO hodne spinave a vlastne nesmyslne reseni...(i kdyz
> trivialni na implementaci).

Ze by to bylo spinave a nesmyslne, to si nemyslim: uz jenom z toho
duvodu, ze pomoci signalu lze rozumne nastavit casovy limit na vetsi
pocet operaci, coz je casto to, co mne opravdu zajima -- je mi ukradene,
jestli connect() trva 1 sekundu nebo 10, ale chci, aby cela transakce
skoncila do 3 minut apod.

Nicmene to neni "trivialni na implementaci", protoze signaly jsou globalni
vlastnost procesu a jsou tedy s nimi stejne problemy jako s globalnimi
promennymi. Zvlaste kdyz clovek pise neco, co ma v umyslu pouzit jako
knihovnu, tak si musi rozmyslet, co muze predpokladat (muze byt nastaveny
nejaky alarm pred vyvolanim me funkce? muze mit SIGALRM nastaveny nejaky
handler?) a jak se vyporadat s tim, kdyz je to tim komplikovanejsim
zpusobem (blokovani signalu po dobu, co menim jeho nastaveni apod.).
Zajimave priklady lze tusim nalezt v glibc (myslim, ze je to nejaka
funkce typu sleep()).

> > oldalarm = signal(SIGALRM, abort_connect);
> > alarm(timeout);
> !!!!!!
> > if (connect(sock, (struct sockaddr *)&s, sizeof(s)) < 0) {
> >         not_connected();
> > }
> > alarm(0);
> > signal(SIGALRM, oldalarm);
> 
> 	Ftip je v tom, ze tam kde jsou '!!!!' neni zaruceno NICIM, ze alarm a
> connect pujdou po sobe, predstavte si, ze mate vytizeny system nebo ze
> se spozdi nejaka I/O HW operace... skocite do obsluhy signalu jeste
> drive nez jste se vubec o connect pokusili... - rozhodne doporucuji
> ciste reseni, tedy non-blocking sockety apod.

Na tom vubec nezalezi. Stejne dobre se muze stat, ze system sice connect()
formalne zahaji, ale nekde se neco zadre a casovy limit vyprsi driv, nez
se dostane k tomu, aby dokoncil navazovani spojeni. Podobne muze dojit
k tomu, ze signal prijde tesne po dokonceni connect() a zavre jiz otevrene
spojeni. Ale v konecnem se dusledku pouze *marginalne* zvysuje riziko
neuspechu, ktere je tak jako tak nenulove.

Jinak close(sock) v handleru signalu je dobry zpusob (close() je povoleno
v signal handleru volat...coz nelze rici o mnoha dalsich funkcich), jak
zajistit, aby connect() selhal, pokud signal *nahodou* prisel uz pred jeho
zahajenim, cili je to prekvapive robustni pristup (jediny problem je, ze
je treba se vyporadat s tim, ze connect() vrati EBADF a pominu-li vyse
diskutovany problem s natahovanim budiku).

--Pavel Kankovsky aka Peak  [ Boycott Microsoft--http://www.vcnet.com/bms ]
"Resistance is futile. Open your source code and prepare for assimilation."



Další informace o konferenci Linux