Ошибка Identifier Removed (EIDRM) при отправке сообщения с очередью IPC

Я использую очередь IPC для синхронизации процессов.

Я всегда получаю ошибку EIDRM при отправке сообщений из очереди IPC, но я вижу, что очередь существует с ipcs.

Я искал 2 часа, но я не вижу ошибки.

следующий код представляет собой урезанную версию, которая дает мне ту же ошибку.

#define CLAVE 53543961
#define TAM_BUFFER 1024
#define PERMISOS 0777
#define DEBUG

int Cola_Mensages;
int msgqid;


typedef struct  {
    long mtype;
    char mtext[TAM_BUFFER];
}msgbuf;


int main (int argc, char *argv[]){
    msgbuf msg_ipc;
    int num_cli,i, i_aux;

    if(argc == 2){
    num_cli = atoi(argv[1]);
    }else{ 
    num_cli = 1;
    }


    //Creating the queue
    if(msgqid = msgget(CLAVE,PERMISOS|IPC_CREAT)<0){
        fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
        exit(0);
    }

    if(msgqid < 0){
        fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
        exit(0);
    }


    for(i = 0;i<num_cli;i++){
       //here i get the error
       i_aux=msgrcv(msgqid,&msg_ipc,TAM_BUFFER,1,0);
       if(i_aux == -1)
           fprintf(stderr,"Error enviando msg ipc %s \n",strerror(errno));
       }

    msg_ipc.mtype = 2;
    strcpy(msg_ipc.mtext,"COMIENZO");
    printf("Enviando msg\n");

       for(i = 0;i<num_cli;i++){
           printf("Enviado msg %d\n",i);
       //here i also get the same error
           if (msgsnd(msgqid,(char *) &msg_ipc,strlen(msg_ipc.mtext),0)!=0)
           {
              fprintf(stderr,"Ocurrio el error %s en msgsnd\n",strerror(errno));
              exit(4);
           }
       }   


    if (msgctl(msgqid,IPC_RMID,(struct msqid_ds *) NULL)<0)
    {
       fprintf(stderr,"Error al borrar la cola de mensajes de clave %d\n",CLAVE);
       exit(4);
    }

    return 0;

}


person Nodens    schedule 16.08.2009    source источник


Ответы (5)


Проблема заключается в неправильной обработке приоритета и порядка вычисления в C всякий раз, когда вы сравните возвращаемое значение msgget со значениями ниже 0:

if(msgqid = msgget(CLAVE,PERMISOS|IPC_CREAT)<0){
    fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
    exit(0);
}

Приоритет оператора присваивания = ниже, чем у оператора сравнения ‹, что подразумевает, что вы присваивали результат msgget() < 0 msgqid и не проверяли, соответствует ли (msgqid = msgget()) < 0.

Затем вы должны заключить присваивание в круглые скобки:

if((msgqid = msgget(CLAVE, PERMISOS | IPC_CREAT)) < 0){
    fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
    exit(0);
}
person Aleksandra Zalcman    schedule 28.12.2011

Задача решена.

Я всегда получал 0 в качестве идентификатора очереди, потому что я вызывал msgget внутри условия if. Я вынул msgget и сделал, если с переменной работает нормально.

person Nodens    schedule 17.08.2009

Просто некоторые идеи,

Вы должны проверить msgget() на -1, чтобы убедиться, что это не удалось.

EIDRM означает «Идентификатор удален», поэтому он соответствует тому, что вы видите в ipcs.

Возможно, сначала вы хотите убедиться, что очередь создана (см. ipcs), и только после этого продолжить отправку/получение сообщений.

person dimba    schedule 16.08.2009
comment
Я уже делаю проверку msgget и кажется правильным. Я не уверен, что понимаю, что вы имеете в виду, что удаление идентификатора согласуется с «ipcs», когда ipcs сообщает мне, что очередь создана. - person Nodens; 16.08.2009

Прекращается ли очередь сообщений, когда вы убиваете этот процесс? То есть вы работаете со свежей очередью каждый раз, когда тестируете? Мне любопытно, действительно ли разрешения такие, как вы думаете.

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

person Rob Jones    schedule 16.08.2009
comment
Да, я работаю с новой очередью каждый раз, когда тестирую, очередь не исчезает, когда я убиваю процесс, я убиваю ее вручную с помощью ipcrm. Позже выложу весь код. - person Nodens; 17.08.2009
comment
Ok. Это странно. Программа работает с первого раза. При первом запуске программы создается очередь сообщений с msqid 0. Прямо сейчас программа не завершается должным образом, поэтому очередь не уничтожается программой должным образом, я должен уничтожить ее с помощью ipcrm -q . После этого каждый раз, когда я перезапускаю программу, я получаю ошибки EIDRM. Ipcs говорит, что очередь создана, но теперь с другим msqid. Кажется, что проблема возникает из-за неправильного закрытия очереди, но мне интересно, почему это приводит к сбою последующих запусков, даже с другим ключом ipc. - person Nodens; 17.08.2009

Ok. Одно обновление о проблеме.

Первый раз запускаю программу, работает отлично. Если я использую ipcs, я вижу, что программа создает очередь с msqid 0. Программа удаляет очередь без проблем.

После первого запуска он перестает работать и начинает выдавать ошибку EIDRM, ipcs говорит, что очередь создана, но у нее нет msqid 0, как при первом запуске, это случайное число. Это происходит, даже если я меняю ipckey, он просто создает еще одну очередь с другим msquid и терпит неудачу так же.

person Nodens    schedule 17.08.2009