Russian Qt Forum
Ноябрь 22, 2024, 20:04 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Очистка очереди  (Прочитано 4109 раз)
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« : Май 27, 2015, 13:09 »

Коллеги, вопрос о том, как выполнить очистку очереди при нештатных ситуациях.

Многопользовательское приложение клиент/сервер. Сервер на Linux, работает в фоновом режиме (демон). Клиент подключается к серверу, отправляет запрос, дожидается ответа и отключается. Сервер при каждом подключении клиента порождает новый процесс (fork), который обслуживает своего клиента. Т.е. дочерних процессов столько, сколько клиентов подключились к серверу.
Одновременно может исполняться только один запрос, поэтому на сервере организована очередь запросов, FIFO. Сейчас она сделана на основе таблицы в БД, но это не принципиально.
Дочерний процесс заносит свой запрос в очередь и ожидает, когда его запрос в очереди не станет первым. Тогда он его исполняет, возвращает результат клиенту, удаляет свой запрос из очереди и завершается.

Проблема возникает, если дочерний процесс по какой-либо причине при завершении не удалил свой запрос (например, аварийно завершился). В этом случае движение очереди останавливается и ни один запрос не будет исполнен. Остальные дочерние процессы подождут и по таймауту завершатся безрезультатно.
Как защититься от такой ситуации? Пока вижу два варианта:
- в главном процессе сервера при обработке сигнала SIGCHLD дочерних процессов проверять очередь, а если запрос завершившегося процесса еще там, удалять. Примерно так:
Код:
    while((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0)
        // удаление запросов завершившегося процесса
        server->cleanupQueue(pid);
- в главном процессе по таймеру, например, раз в секунду, читать все запросы из очереди и проверять по PID наличие работающих дочерних процессов. Ну и чистить, при необходимости.

Есть еще какие-нибудь варианты? Или в консерватории нужно что-то поправить? Улыбающийся
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #1 : Май 28, 2015, 14:25 »

Сейчас она сделана на основе таблицы в БД, но это не принципиально.
Вот тут я ошибался. В главном (родительском) процессе работать с БД (а у меня PostgreSQL) нельзя. Потому как если в момент, когда база открыта, производится вызов fork, то результат непредсказуем. У меня программа иногда зависала.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Akon
Гость
« Ответ #2 : Май 29, 2015, 12:12 »

Должна быть симметрия. Если вы создаете данные в родительском процессе, то в нем же и удаляйте мусор. Операционная система тоже частенько подчищает за нами Улыбающийся
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #3 : Май 29, 2015, 12:25 »

Данные создаются в дочернем процессе (при подсоединении клиента ему выделяется процесс, в котором запрос и ставится в очередь). А чистить должен родительский, т.к. он единственный, который работает все время (типа postmaster).
Я пока сделал так: при завершении любого дочернего процесса форкается вспомогательный "чистильщик", который и убирает мусор за этим завершившимся процессом.
Как-то не здорово.. Наверное, я что-то намудрил.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.084 секунд. Запросов: 22.