Есть несколько способов сделать это, вот пара других идей для вас. Идея обоих заключается в том, что владелец сокета (то есть поток выполняет закрытие, а не другой поток).
Добавьте управляющий сокет к вашему набору чтения в вызове выбора, например, Unix сокет. Напишите некоторые управляющие данные, чтобы отделить этот поток от вызова select. Затем поток может проверить, должен ли сокет быть закрыт или нет. Может сделать это как часть структуры вашего сокета или даже как фактические данные вашего контрольного пакета.
, например
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(sock, &readSet);
FD_SET(controlSock, &readSet);
int n = select(maxfd, &readSet, NULL, NULL);
...
if (FD_ISSET(controlSock, &readSet)) {
/* check if sock should be closed or not, also drain controlSock */
}
, затем просто напишите в управляющий разъем, чтобы подать сигнал на закрытие.
Вы также можете вызвать сигнал, который обычно прерывает блокирующий вызов ввода-вывода. Если они не будут перезапущены автоматически. Вызовы вернут -1, и errno будет установлен в EINTR. Вы можете проверить флажок, чтобы увидеть, следует ли вам закрыться и прервать разговор.
1012 *, например *
if (n == -1 && errno == EINTR)
goto cleanup;