У меня есть набор программ клиент-сервер TCP, который работает без проблем более 10 лет.Задание 'head' порождает тело дочерних процессов (я на платформе AS400, которая не поддерживает fork () / exec ()).Головное задание настраивается в качестве TCP-сервера, и, как только устанавливается соединение, оно сразу же раздает соединение с одним из дочерних заданий с помощью sendmsg ().Используется обычный шаблон socketpair () и т. Д.Я признаю, что когда я собирал все это вместе 12 лет назад, я не понимал всего, что происходило.Код, который я нашел для пропуска открытого соединения, приведен ниже.Итак, головное задание ожидает вызова accept () и вызывает sendfd (), когда accept () возвращает.
int sendfd(int s, int fd)
{
char buf[1];
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsg;
int n;
char cms[CMSG_SPACE(sizeof(int))];
buf[0] = 0;
iov.iov_base = buf;
iov.iov_len = 1;
memset(&msg, 0, sizeof msg);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = (caddr_t)cms;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memmove(CMSG_DATA(cmsg), &fd, sizeof(int));
if ((n = sendmsg(s, &msg, 0)) != iov.iov_len) {
return -1;
}
return 0;
}
Итак, дочерние задания запускают подпрограмму для получения соединения.Это ниже.Пул дочерних процессов эффективно выполняет эту подпрограмму наподобие "recvfd (0);"В нашем отделе обеспечения качества будет проведен автоматизированный тест, и с прошлой недели весь набор дочерних процессов умрет, по-видимому, случайным образом, с точностью до секунды, с EWOULDBLOCK.Я смущен этой ошибкой.recvmsg () всегда блокируется, ожидая сообщения.Ошибка относится к принимаемому сокету или к «0», для которого он используется?Ничто в моем коде не меняет качества файлового дескриптора 0. Я действительно удивлен, почему умирает весь набор дочерних процессов.Что-то говорит мне, что дескриптор файла 0 изменяется, но в коде нет ничего для любой программы, которая делает какие-либо манипуляции, подобные этой.
int recvfd(int s)
{
int ret, fd;
char buf[1];
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsg;
char cms[CMSG_SPACE(sizeof(int))];
iov.iov_base = buf;
iov.iov_len = 1;
memset(&msg, 0, sizeof msg);
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = (caddr_t)cms;
msg.msg_controllen = sizeof cms;
if ((ret = recvmsg(s, &msg, 0)) < 0) {
return -1;
}
if (ret == 0) {
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
memmove(&fd, CMSG_DATA(cmsg), sizeof(int));
return fd;
}
Я могу опубликовать больше кода, если потребуется больше подробностей.Я должен найти эту ошибку сразу, так как она является ядром нашего бизнеса.Заранее спасибо!
РЕДАКТИРОВАТЬ: Вот фрагмент из дочернего кода.Посмотрите, что 'worker_sd' явно установлен на 0. Проблема, которую мне нужно исправить, состоит в том, что выход из цикла означает выход из программы, но я не знаю, есть ли способ справиться с этой ошибкой.
сообщение об ошибке в конечном итоге будет: дочерний объект транзакции завершается с new_sock = -1 и ошибкой = операция привела бы к приостановке процесса.
// worker_sd is explicitly set to 0 because the parent set the child's 0 file descriptor (the usual one
// reserved for standard input) to be the socket over which open descriptors come.
int worker_sd = 0;
jobSwitches.get();
logging_on = jobSwitches[QQJobSwitches::LOGGING_ON] == '1';
debug_on = jobSwitches[QQJobSwitches::DEBUG_ON] == '1';
wait_on_child_process = jobSwitches[QQJobSwitches::WAIT_ON_CHILD] == '1';
if (debug_on) {
CERR << "START: Waiting for a message..." << endl;
}
while ((new_sock = recvfd(worker_sd)) >= 0) {
stringstream sstr;
string ip_str, port_str;
bool success;