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