Gniazda na pytanie LinuxPobudka wątek zablokowany na accept() zadzwoń
Mam wątek roboczy, który jest zablokowany w wywołaniu accept(). Po prostu czeka na przychodzące połączenie sieciowe, obsługuje je, a następnie wraca do nasłuchu na następne połączenie.
Kiedy nadejdzie czas zakończenia programu, w jaki sposób zasygnalizuję ten wątek pracownika sieci (z głównego wątku), aby powrócił z wywołania accept(), wciąż będąc w stanie zręcznie opuścić pętlę i obsłużyć jej kod oczyszczający .
Niektóre rzeczy próbowałem:
pthread_kill wysłać sygnał. Czuje się kludgy, aby to zrobić, a ponadto nie pozwala niezawodnie wątku na jego logikę zamykania. Powoduje także zakończenie programu. Chciałbym unikać sygnałów, jeśli to w ogóle możliwe.
pthread_cancel. Jak powyżej. To ostre zabójstwo na wątku. To i wątek może robić coś innego.
Zamknięcie gniazda nasłuchiwania z głównego wątku w celu wykonania funkcji accept(). To nie działa niezawodnie.
pewne ograniczenia:
Jeżeli rozwiązanie wymaga podejmowania słuchać gniazda nieblokujące, że jest w porządku. Ale nie chcę zaakceptować rozwiązania, które obejmuje wątek budzący się przez wywołanie select co kilka sekund, aby sprawdzić warunki wyjścia.
Warunek wątku do wyjścia nie może być związany z zakończeniem procesu.
Zasadniczo logika, do której zmierzam, wygląda tak.
void* WorkerThread(void* args)
{
DoSomeImportantInitialization(); // initialize listen socket and some thread specific stuff
while (HasExitConditionBeenSet()==false)
{
listensize = sizeof(listenaddr);
int sock = accept(listensocket, &listenaddr, &listensize);
// check if exit condition has been set using thread safe semantics
if (HasExitConditionBeenSet())
{
break;
}
if (sock < 0)
{
printf("accept returned %d (errno==%d)\n", sock, errno);
}
else
{
HandleNewNetworkCondition(sock, &listenaddr);
}
}
DoSomeImportantCleanup(); // close listen socket, close connections, cleanup etc..
return NULL;
}
void SignalHandler(int sig)
{
printf("Caught CTRL-C\n");
}
void NotifyWorkerThreadToExit(pthread_t thread_handle)
{
// signal thread to exit
}
int main()
{
void* ptr_ret= NULL;
pthread_t workerthread_handle = 0;
pthread_create(&workerthread, NULL, WorkerThread, NULL);
signal(SIGINT, SignalHandler);
sleep((unsigned int)-1); // sleep until the user hits ctrl-c
printf("Returned from sleep call...\n");
SetThreadExitCondition(); // sets global variable with barrier that worker thread checks on
// this is the function I'm stalled on writing
NotifyWorkerThreadToExit(workerthread_handle);
// wait for thread to exit cleanly
pthread_join(workerthread_handle, &ptr_ret);
DoProcessCleanupStuff();
}
'pthread_kill()' wysyła sygnał do wątku, nic więcej, nic mniej. I niekoniecznie "* powoduje, że program się kończy *". – alk
"* pthread_cancel. Tak jak powyżej. *" Err, co? Nie, 'pthread_cancel()' robi coś zupełnie innego niż 'pthread_kill()'! Proszę RTFM. – alk
Jednym z łatwych sposobów na uzyskanie akceptacji() w celu powrotu jest otwarcie połączenia TCP z portem, na którym nasłuchuje połączenie accept(). –