Как присоединиться к ветке, которая висит на блокировке ввода-вывода? - PullRequest
27 голосов
/ 15 октября 2008

У меня есть поток, работающий в фоновом режиме, который читает события с устройства ввода блокирующим образом, теперь, когда я выхожу из приложения, я хочу правильно очистить поток, но я не могу просто запустить pthread_join () потому что поток никогда не выйдет из-за блокирования ввода-вывода.

Как мне правильно решить эту ситуацию? Должен ли я отправить pthread_kill (theard, SIGIO) или pthread_kill (theard, SIGALRM), чтобы разбить блок? Является ли это даже правильным сигналом? Или есть другой способ разрешить эту ситуацию и позволить этому дочернему потоку выйти из блокирующего чтения?

В настоящее время немного озадачен, так как никто из моих поисков не нашел решения.

Это в Linux и использует pthreads.

Edit: я немного поигрался с SIGIO и SIGALRM, когда я не устанавливаю обработчик сигнала, они ломают блокирующий ввод-вывод, но выдают сообщение на консоли («I / O возможен»), но когда я устанавливаю обработчик сигнала, чтобы избежать этого сообщения, они больше не нарушают блокировку ввода-вывода, поэтому поток не завершается. Так что я вернулся к первому шагу.

Ответы [ 13 ]

0 голосов
/ 15 октября 2008
struct pollfd pfd;
pfd.fd = socket;
pfd.events = POLLIN | POLLHUP | POLLERR;
pthread_lock(&lock);
while(thread_alive)
{
    int ret = poll(&pfd, 1, 100);
    if(ret == 1)
    {
        //handle IO
    }
    else
    {
         pthread_cond_timedwait(&lock, &cond, 100);
     }
}
pthread_unlock(&lock);

thread_alive - переменная, специфичная для потока, которая может использоваться в сочетании с сигналом для уничтожения потока.

Что касается секции дескриптора ввода-вывода, вам необходимо убедиться, что вы использовали open с опцией O_NOBLOCK, или, если для сокета существует подобный флаг, вы можете установить MSG_NOWAIT ?? для других fds я не уверен

0 голосов
/ 15 октября 2008

Я думаю, что в самом чистом подходе поток будет использовать условные переменные в цикле для продолжения.

При возникновении события ввода-вывода должно быть указано условное условие.

Основной поток мог просто сигнализировать об условии, изменяя предикат цикла на false.

что-то вроде:

while (!_finished)
{
    pthread_cond_wait(&cond);
    handleio();
}
cleanup();

Помните с условными переменными, чтобы правильно обрабатывать сигналы. У них могут быть такие вещи, как «ложные пробуждения». Поэтому я бы обернул вашу собственную функцию вокруг функции cond_wait.

0 голосов
/ 15 октября 2008

Сигналы и поток - это тонкая проблема в Linux, согласно различным страницам руководства. Используете ли вы LinuxThreads или NPTL (если вы используете Linux)?

Я не уверен в этом, но я думаю, что обработчик сигнала влияет на весь процесс, поэтому либо вы завершаете весь процесс, либо все продолжается.

Вы должны использовать таймер выбора или опроса и установить глобальный флаг, чтобы прервать ваш поток.

...