LINUXSOFT.cz
Nazwa użytkownika: Hasło:     
    CZ UK PL

> Komentarze :: Poradna Lze oživit vlákno zablokované na read()?

Lze oživit vlákno zablokované na read()? 27.11.2007 01:13
Jan Němec

Píšu v C malý servřík, mám vše v jednom procesu (žádné fork, exec), používám vlákna (pthread_create) a sockety. Hlavní vlákno většinu času spí na accept(), vlákno obsluhující klienta spí na read(), používám totiž blokovací režim socketu, ktery mi vyhovuje. Pak mám ještě ovládací vlákno, které server řídí.

A teď problém. Řídící vlákno usoudí, že vlákno klienta má 1) ukončit ten zablokovaný read() a 2) hlavní vlákno accept(). Samozřejmě nechci ta vlákna odbouchnout, chci jen aby read a accept skoncily s chybou a vlakno dal jelo.

add 1) Jde to vubec nejak? Nebo to musim obchazet pres neblokovaci rezim a select a pomocny file descriptor typu pipa, kterym ten select probudim.

add 2) Jde to nejak elegantneji nez close(socket) a poslanim signalu sam sobe?

Diky moc za pripadne rady, fakt jsem to nevygooglil.

Re: Lze oživit vlákno zablokované na read()? 27.11.2007 01:52
Aleš Hakl

Prakticky vsechna systemove volani, ktera se umeji zablokovat lze prerusit. A to zaslanim signalu, ktery ma nejakou obsluznou funkci. Ovsem je to spise takovy implementacni detail obsluhy signalu a napriklad SUSv3 toto specifikuje dosti nejasne (nikde neni receno jestli to funguje vzdy). Je to elegantni treba na niceni zombie procesu ve smycce accept()-fork() nejakeho serveru (tj. na neco, kde kdyz to nefunguje nicemu az tak moc nevadi).

Pokud o to nejak zajimave jde, tak bych asi pouzil ten neblokujici rezim a select().

Vzhledem k tomu, ze stejne neni dobry napad mit v programu nejake nahodne vyskyty volani typu read() a write(), tak bych si napsal wrapper, ktery bude nad neblokujicim socketem emulovat blokujici read() (pomoci nejakeho select() nebo poll()) + osetrovat stavy typu "read vratil EINTR".

Re: Lze oživit vlákno zablokované na read()? 27.11.2007 08:35
Jan Němec

Díky za odpověď.

Tak jsem to nakonec napsal s tou pípou. Funguje to, ale vůbec se mi to nelíbí. Pokud se najde nějaký linuxový C machr, budu vděčný za připomínky.

Takhle jsem to napsal:
// Vlákno čtení od klienta
while (1) {
char c;
fd_set r;
FD_ZERO(&r);
FD_SET(fd, &r);
FD_SET(pipa[0], &r);
select((fd > pipa[0] ? fd : pipa[0]) + 1, &r, NULL, NULL, NULL);
if (FD_ISSET(pipa[0], &r)) break;
if (read(fd, (void *)&c, 1) != 1) break;
// tady něco dělám s tím bytem
}

// Vlakno koncici cyklus cteni

close(fd);
char nejakej_byte = 0;
write(pipa[1], (void *)&nejakej_byte, 1);

Místo aby to šlo prostě takhle:

// Vlákno čtení od klienta
while (1) {
select((fd > pipa[0] ? fd : pipa[0]) + 1, &r, NULL, NULL, NULL);
// tady něco dělám s tím bytem
}

// Vlakno končící cyklus čtení

close(fd); // Nefunguje!!! Volání close neukončí zablokovaný read.

Re: Lze oživit vlákno zablokované na read()? 3.12.2007 13:13
Tomáš "Atom" Klas

Zkuste nejprve shutdown() a potom close(). Může to pomoci, ale nespoléhal bych se na přenositelnost.

Také by mohlo pomoci místo select() použít poll() s flagem POLLHUP. Bohužel poll() je čistě Linuxové volání, ale zase mnohem lépe řešené než select().

Obávám se, že řešení s pipe() je jediné spolehlivé.

Re: Lze oživit vlákno zablokované na read()? 4.12.2007 13:39
Oldrich Pikhart

Pokud vim, tak poll() neni ciste Linuxova vec viz.:
http://www.opengroup.org/onlinepubs/009695399/functions/poll.html
Linuxova vec je tusim az epoll.

Re: Lze oživit vlákno zablokované na read()? 7.5.2010 09:28
Jan Němec

Díky za radu s tím shotdownem. Náhodou jsem po 2 a půl letech řešil stejný problém. Portoval jsem nějakou C++ knihovnu z iPhone na Android. Na iPhone to close odblokovalo spící recvfrom, ale na Androidu ne. Zkusil jsem to shutdown a zabralo to. Ušetřil jste mi pípování.


KOMENTARZE
Lze oživit vlákno zablokované na read()? 27.11.2007 01:13 Jan Němec
  L Re: Lze oživit vlákno zablokované na read()? 27.11.2007 01:52 Aleš Hakl
    L Re: Lze oživit vlákno zablokované na read()? 27.11.2007 08:35 Jan Němec
      L Re: Lze oživit vlákno zablokované na read()? 3.12.2007 13:13 Tomáš "Atom" Klas
        |- Re: Lze oživit vlákno zablokované na read()? 4.12.2007 13:39 Oldrich Pikhart
        L Re: Lze oživit vlákno zablokované na read()? 7.5.2010 09:28 Jan Němec
Tylko zarejestrowani użytkownicy mogą dopisywać komentarze.
> Szukanie oprogramowania
1. Pacman linux
Download: 4698x
2. FreeBSD
Download: 8874x
3. PCLinuxOS-2010
Download: 8378x
4. alcolix
Download: 10644x
5. Onebase Linux
Download: 9444x
6. Novell Linux Desktop
Download: 0x
7. KateOS
Download: 5935x

1. xinetd
Download: 2226x
2. RDGS
Download: 937x
3. spkg
Download: 4317x
4. LinPacker
Download: 9581x
5. VFU File Manager
Download: 3019x
6. LeftHand Mała Księgowość
Download: 6833x
7. MISU pyFotoResize
Download: 2592x
8. Lefthand CRM
Download: 3387x
9. MetadataExtractor
Download: 0x
10. RCP100
Download: 2859x
11. Predaj softveru
Download: 0x
12. MSH Free Autoresponder
Download: 0x
©Pavel Kysilka - 2003-2024 | mailatlinuxsoft.cz | Design: www.megadesign.cz