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