Russian Qt Forum

Программирование => Алгоритмы => Тема начата: sergek от Май 27, 2015, 13:09



Название: Очистка очереди
Отправлено: sergek от Май 27, 2015, 13:09
Коллеги, вопрос о том, как выполнить очистку очереди при нештатных ситуациях.

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

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

Есть еще какие-нибудь варианты? Или в консерватории нужно что-то поправить? :)


Название: Re: Очистка очереди
Отправлено: sergek от Май 28, 2015, 14:25
Сейчас она сделана на основе таблицы в БД, но это не принципиально.
Вот тут я ошибался. В главном (родительском) процессе работать с БД (а у меня PostgreSQL) нельзя. Потому как если в момент, когда база открыта, производится вызов fork, то результат непредсказуем. У меня программа иногда зависала.


Название: Re: Очистка очереди
Отправлено: Akon от Май 29, 2015, 12:12
Должна быть симметрия. Если вы создаете данные в родительском процессе, то в нем же и удаляйте мусор. Операционная система тоже частенько подчищает за нами :)


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