Сокеты по Linux вопрос
У меня есть рабочий поток, заблокированный при вызове accept (). Он просто ожидает входящего сетевого подключения, обрабатывает его и затем возвращается к прослушиванию следующего подключения.
Когда пришло время для выхода из программы, как я могу сигнализировать этому сетевому рабочему потоку (из основного потока) вернуться из вызова accept (), при этом все еще имея возможность корректно выйти из своего цикла и обработать свой код очистки.
Некоторые вещи, которые я пробовал:
pthread_kill для отправки сигнала. Чувствует себя глупо, делая это, плюс он не позволяет потоку делать логику отключения. Также заставляет программу завершаться. Я хотел бы избежать сигналов, если это вообще возможно.
pthread_cancel. То же, что и выше. Это резкое убийство в потоке. Это, и поток может делать что-то еще.
Закрытие сокета прослушивания из основного потока для прерывания accept (). Это не работает надежно.
Некоторые ограничения:
Если решение заключается в том, чтобы сделать прослушивающий сокет неблокирующим, это нормально. Но я не хочу принимать решение, которое включает в себя пробуждение потока через вызов select каждые несколько секунд для проверки условия выхода.
Условие потока для выхода может не быть связано с процессом выхода.
По сути, логика, к которой я стремлюсь, выглядит следующим образом.
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();
}