Не удается разблокировать / "разбудить" тему с помощью pthread_kill & sigwait - PullRequest
2 голосов
/ 05 апреля 2011

Я работаю над сетевым проектом на C / C ++ и испытываю трудности с синхронизацией / сигнализацией своих потоков.Вот что я пытаюсь выполнить:

  1. Опрос группы сокетов с помощью функции poll
  2. Если какие-либо сокеты готовы из события POLLIN, то отправьте сигнал потоку читателяи поток писателя для «пробуждения»

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

Проблема в том, что я проверяю все эти функции, отправляя сигнал потоку, но он никогда не просыпается.

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

Ошибка может быть очевидной (это не синтаксическая ошибка - приведенный выше код сжат из компилируемого кода, и я мог бы испортить его при редактировании)но я просто не могу найти / увидеть это, так как потратил много времени на эту проблему и запутался.

Позвольте мне объяснить, что я думаю, и если это имеет смысл.

  1. После создания объекта типа MessageHandler он установит для allowSignalsMask значение одного сигнала (на данный момент), который я заинтересован в использовании для пробуждения моих потоков.
  2. Iдобавьте сигнал к заблокированным сигналам текущего потока с помощью pthread_sigmask.Все остальные потоки, созданные после этой точки, должны теперь иметь одинаковую маску сигналов.
  3. Затем я создаю поток чтения с помощью pthread_create, где arg - указатель на объект типа MessageHandler.
  4. Я вызываюспать как дешевый способ убедиться, что мой readerThread выполняется до sigwait ()
  5. Я посылаю сигнал SIGCONT на reader, считывая, что меня интересует sigwait, чтобы разбудить / разблокировать после его получения.
  6. Снова я называю сон дешевым способом гарантировать, что мой readerThread может выполнить все время после того, как он проснулся / разблокирован от sigwait ()

Другие полезные заметки, которые могут быть полезны, но я неНе думаю, что повлиять на проблему:

  • MessageHandler создается, а затем создается другой поток, учитывая указатель функции, который указывает на запуск.Этот поток будет отвечать за создание потоков чтения и записи, опроса сокетов с помощью функции poll, а затем, возможно, отправки сигналов в потоки чтения и записи.

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

Еще раз спасибо.

Ответы [ 3 ]

5 голосов
/ 05 апреля 2011

У потоков POSIX есть условные переменные по причине используй их. От вас не требуется взлома сигналов для выполнения основных задач синхронизации при программировании с потоками.

Вот хороший учебник pthread с информацией об использовании условных переменных:

https://computing.llnl.gov/tutorials/pthreads/

Или, если вам удобнее использовать семафоры, вместо этого вы можете использовать семафоры POSIX (sem_init, sem_post и sem_wait). Но как только вы выясните, почему сопряжение условной переменной и мьютекса имеет смысл, я думаю, вы обнаружите, что условные переменные являются гораздо более удобным примитивом.

Кроме того, обратите внимание, что ваш текущий подход использует несколько системных вызовов (переходы пользовательского пространства / пространства ядра) для каждой синхронизации. При хорошей реализации pthreads использование условных переменных должно сбрасывать это не более чем на один системный вызов, и, возможно, на ноль вообще, если ваши потоки не отстают друг от друга настолько, что происходит ожидаемое событие, пока они все еще вращаются в пространстве пользователя. .

1 голос
/ 05 апреля 2011

Этот шаблон кажется немного странным и, скорее всего, подвержен ошибкам.Библиотека pthread богата методами синхронизации, наиболее подходящими для вашей потребности являются семейства pthread_cond_*.Эти методы обрабатывают условные переменные , которые реализуют подход Ожидание и Сигнал.

0 голосов
/ 21 апреля 2011

Используйте SIGUSR1 вместо SIGCONT.SIGCONT не работает.Возможно, эксперт по сигналам знает, почему.

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

R.указывает на дополнительные издержки из-за дополнительных вызовов пространства ядра.Возможно, если вы спите> N потоков, то одна переменная условия выбьет несколько сигвей и pthread_kills.В нашем приложении мы хотим разбудить только один поток, когда придет работа.Вы должны иметь условную переменную и мьютекс для каждого потока, чтобы сделать это, иначе вы получите давку.В тесте, где мы спали и просыпались по N нитям M раз, сигналы били мьютексы и переменные состояния в 5 раз (это могло быть в 40 раз, но я не могу вспомнить больше .... ааа).Мы не тестировали Futexes, которые могут пробуждать 1 поток за раз и специально закодированы для ограничения поездок в пространство ядра.Я подозреваю, что фьютексы будут быстрее, чем мьютексы.

...