У меня есть многопоточный серверный процесс, написанный на C / C ++, который я пытаюсь профилировать с помощью Google perftools. Однако когда я запускаю процесс с perftools, довольно скоро мой сервер останавливается с ошибкой «syscall прервана», которая, я думаю, вызвана входящим SIGPROF. (Фактический прерываемый системный вызов находится глубоко внутри моего вызова zmq_recv, но я не думаю, что это действительно важно, какой это.)
Это ожидаемое поведение? Должен ли я как-то явно заниматься этим делом? Или здесь что-то идет не так?
Из документации zeroMQ для zmq_recv () мы можем ожидать его возвращения EINTR
если сигнал получен, когда он выполняется.
Генерация сигналов прямо в середине zmq_recv()
вызов будет сложной задачей для любого теста. к счастью gperftools производя тонну SIGPROF
s обнаружил эту тонкую «ошибку» в вашем коде.
это должен быть изящным ваш код в качестве структуры zeroMQ является изящно сдающим контроль. Логика повторения может быть такой же простой, как изменение существующего вызова:
/* Block until a message is available to be received from socket */
rc = zmq_recv (socket, &part, 0);
с новым (с логикой повторения) следующим образом:
/* Block until a message is available to be received from socket
* Keep retrying if interrupted by any signal
*/
rc = 0;
while(rc != EINTR) {
rc = zmq_recv (socket, &part, 0);
}
Также установить функцию обработчика сигнала в вашей программе. Можно просто игнорировать прерывание из-за SIGPROF
и продолжайте повторять.
Наконец, вы можете обрабатывать определенные сигналы и действовать соответственно. Например, изящное завершение вашей программы, даже если пользователь нажимает CTRL+С пока ваша программа ожидает zmq_recv()
.
/* Block until a message is available to be received from socket
* If interrupted by any signal,
* - in handler-code: Check for signal number and update status accordingly.
* - in regular-code: Check for status and retry/exit as appropriate
*/
rc = 0;
while(rc != EINTR && status == RETRY) {
rc = zmq_recv (socket, &part, 0);
}
В целях сохранения кода «чистым» вам будет лучше использовать приведенный выше фрагмент кода для написания собственного static inline
функциональная оболочка вокруг zmq_recv()
который вы можете назвать в своей программе.
Относительно решения сделать zmq_recv()
вернуть EINTR
после получения сигналов вы можете ознакомиться с этой статьей, в которой говорится о хуже — лучше философия за такой дизайн, который проще с точки зрения реализации.
ОБНОВИТЬ: Документированный код для обработки сигналов в контексте zmq_recv()
доступен на git.lucina.net/zeromq-examples.git/tree/zmq-camera.c. Это в том же духе, как описано выше, но выглядит хорошо протестированным и готовым к использованию с подробными комментариями, любезно разбросанными повсюду (yayyy zeromq!).
Других решений пока нет …