C - Thread a select()

Josko

C - Thread a select()
« kdy: 31. 10. 2017, 08:45:23 »
Ahojte,

O co mi ide, mam thread ktory obsahuje funkciu select(), ako je nizsie uvedena. Timeout je nastaveny na 3FFFF.
Existuje nejake elegantne riesenie, ako "zobudit" select(), a nasledne aj ukoncit thread - select_thread?

Momentalne to riesim tak, ze v threade si zaregistrujem SIGNAL - SIGUSR, a v parentovi, poslem cez pthread_kill(SIGUSR). Samozrejme, po tomto select() vrati hodnotu -1 a errno = 4 (system interrupt).

Hladam elegantnejsie riesenie, alebo, je toto "standardne" riesenie?

thread_select.c:
...
static void * select_thread(void * n);

...
Zaregistrovanie, nastavenie sigmask, sigset...
...
for(;;){
result = select(nfds, &readfds, NULL, NULL, &timeout);

if(result == -1 && errno == 4)
 break;
}
  /* loop successfuly ended */

main.c

result = pthread_create(ptrselect_thread, select_thread,...);

/* ...*/

result = pthread_kill(select_thread, SIGUSR1);
if(result == 0)
 pthread_join(...)

Diky.


M.

Re:C - Thread a select()
« Odpověď #1 kdy: 31. 10. 2017, 09:16:40 »
Ano, je to možné řešení. Jiný postup, pokud je cílem vlákno jen ukončit a netřeba, aby cokoliv dalšího dělalo, tak použít pthread_cancel(), protože select je povinný cancel point, tak bude vlákno přímo ukončeno, pokud bude v select čekat (pokud má vlákno default stavy nastaveno PTHREAD_CANCEL_ENABLE a PTHREAD_CANCEL_DEFERRED,  viz funkce pthread_setcancelstate()  a pthread_setcanceltype() ).

borekz

  • ****
  • 492
    • Zobrazit profil
    • E-mail
Re:C - Thread a select()
« Odpověď #2 kdy: 31. 10. 2017, 09:46:10 »
eventfd

Re:C - Thread a select()
« Odpověď #3 kdy: 31. 10. 2017, 10:16:43 »
Jestli chceš ukončit čekání a zavřít spojení, pak nejspravnejsi postup je shutdown socketu na SHUT_RD. To způsobí že select skončí a recv operace vrátí nulu jako by spojení zavřela druhá strana

Pokud chceš budit to vlákno jindy, pak to dělám tak že mám jedno extra lokální spojení (v Linuxu roury) a jeden konec poslouchám selectem a do druhého pošlu bajt a select thread se probudí. Na Windows stačí udp socket který sám sobě pošle zpravu.

V Linuxu je select bezpečnostní hrozba, doporucuju použít poll nebo epoll. Ve windows se select používá jako poll, doporučuji si napsat Windows emulaci pollu právě přes jeho select

Re:C - Thread a select()
« Odpověď #4 kdy: 31. 10. 2017, 15:14:02 »
Ano, je to možné řešení. Jiný postup, pokud je cílem vlákno jen ukončit a netřeba, aby cokoliv dalšího dělalo, tak použít pthread_cancel(), protože select je povinný cancel point, tak bude vlákno přímo ukončeno, pokud bude v select čekat (pokud má vlákno default stavy nastaveno PTHREAD_CANCEL_ENABLE a PTHREAD_CANCEL_DEFERRED,  viz funkce pthread_setcancelstate()  a pthread_setcanceltype() ).

V žádném případě nedoporučju používat. Stabilní program nechá své vlákna deterministicky dojít do konce kódu. Dokážu si představit, že ve zrušeném vláknu se nezavolají různé čistící bloky kódy, které jsou za selectem, v C++ například destruktory, atd.


M.

Re:C - Thread a select()
« Odpověď #5 kdy: 31. 10. 2017, 15:35:18 »
Ano, je to možné řešení. Jiný postup, pokud je cílem vlákno jen ukončit a netřeba, aby cokoliv dalšího dělalo, tak použít pthread_cancel(), protože select je povinný cancel point, tak bude vlákno přímo ukončeno, pokud bude v select čekat (pokud má vlákno default stavy nastaveno PTHREAD_CANCEL_ENABLE a PTHREAD_CANCEL_DEFERRED,  viz funkce pthread_setcancelstate()  a pthread_setcanceltype() ).

V žádném případě nedoporučju používat. Stabilní program nechá své vlákna deterministicky dojít do konce kódu. Dokážu si představit, že ve zrušeném vláknu se nezavolají různé čistící bloky kódy, které jsou za selectem, v C++ například destruktory, atd.
Pokud vlákno musí něco po sobě čistit, tak od toho snad mám pthread_cleanup_push(), kterým průběžně ukládám čisící kód, který se při ukončení vlákna vykoná v pořadí, jak byl napushován a je jedno, zda vlákno končí kvůli return/pthread_exit()/pthread_cancel() ).

Re:C - Thread a select()
« Odpověď #6 kdy: 31. 10. 2017, 16:30:48 »

V žádném případě nedoporučju používat. Stabilní program nechá své vlákna deterministicky dojít do konce kódu. Dokážu si představit, že ve zrušeném vláknu se nezavolají různé čistící bloky kódy, které jsou za selectem, v C++ například destruktory, atd.
Pokud vlákno musí něco po sobě čistit, tak od toho snad mám pthread_cleanup_push(), kterým průběžně ukládám čisící kód, který se při ukončení vlákna vykoná v pořadí, jak byl napushován a je jedno, zda vlákno končí kvůli return/pthread_exit()/pthread_cancel() ).

Mně se tohle nelíbí, to je totiž stejný mechanismus jako atexit. Jenže zatímco u exitu finalní čistění udělá operační systém, u threadů je to větší průser. Jakou jistotu máte, že to dělají všechny části kódu? Rozlišujete nějak v knihovnách, jestli běží ve vlákně, nebo v ... hlavním vlákně, kde se to běžně nedělá? Co když tam zamýchám C++ který prokazatelně destrukci objektů nenavěšuje na tenhle event?

Ne, fakt to nepoužívejte, nadělá to víc škody než užitku. V C++ už tuplem ne. To je lepší MT navrhovat tak, aby vždy existovala cesta, jak opustit nějakou aktuální činnost a spořádaným způsobem ukončit všechny funkce returnem až na tu základní úroveň. (případně výjimkou zachycenou na základní úrovni)

pthread_exit() si zavolá ten kdo volal tu mojí vstupní funkci, to už je jeho starost.
« Poslední změna: 31. 10. 2017, 16:32:19 od Ondřej Novák »

Josko

Re:C - Thread a select()
« Odpověď #7 kdy: 03. 11. 2017, 09:41:48 »
Diky za help, vyriesil som to cez pipes ... v select som zaregistroval dva fd, oba pre read... cez FD_ISSET() zistim kde prisli data.. ked z mojej pipe, spravim resolve, a uzatvorim pripadne spojenie.

Diky za pomoc