繁体   English   中英

消息队列:通知中的错误文件描述符

[英]Message queues: Bad file descriptor in notification

我创建了一个 mq 文件描述符表,我试图通过其中一个从标准输入传递数字。

我正在使用线程使用通知,当其中一个队列中出现一个数字时,它应该打印例如“Number: 1 from queue: 3”。

这是我的代码:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <mqueue.h>

#define MAX_LENGTH 20

#define ERR(source) (\
    fprintf(stderr, "%s:%d\n", __FILE__, __LINE__),\
    perror(source),\
    kill(0, SIGKILL),\
    exit(EXIT_FAILURE)\
)

static void not_func(union sigval sv) {
    mqd_t queue;
    uint8_t number;
    unsigned msg_prio;

    queue = *((mqd_t*)sv.sival_ptr);

    static struct sigevent not;
    not.sigev_notify = SIGEV_THREAD;
    not.sigev_notify_function = not_func;
    not.sigev_value.sival_ptr = &queue;
    if(mq_notify(queue, &not)<0) ERR("mq_notify");

    for(;;) {
        if(mq_receive(queue, (char*)&number, 1, &msg_prio)<1) {
            if(errno == EAGAIN) break;
            else ERR("mq_receive");

            printf("Number: %d from queue: %d", number, msg_prio);
        }
    }
}

void get_queue_name(int nr, char *str) {
    snprintf(str, MAX_LENGTH, "/queue%d", nr);
}

mqd_t create_message_queue(int nr) {
    mqd_t queue;
    char name[MAX_LENGTH] = "";
    get_queue_name(nr, name);

    struct mq_attr attr;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 1;

    if((queue = TEMP_FAILURE_RETRY(mq_open(name, O_RDWR|O_NONBLOCK|O_CREAT, 0600, &attr))) == (mqd_t)-1) ERR("mq open in");

    static struct sigevent not;
    not.sigev_notify = SIGEV_THREAD;
    not.sigev_notify_function = not_func;
    not.sigev_value.sival_ptr = &queue;
    if(mq_notify(queue, &not)<0) ERR("mq_notify");

    return queue;
}

void delete_message_queue(mqd_t queue, int nr) {
    char name[MAX_LENGTH] = "";
    get_queue_name(nr, name);

    mq_close(queue);
    if(mq_unlink(name)) ERR("mq_unlink");
}

void usage(void) {
    fprintf(stderr, "USAGE: mqueue n\n");
    fprintf(stderr, "100 > n > 0 - number of children\n");
    exit(EXIT_FAILURE);
}

int main(int argc, char **argv) {
    int n, i;
    char strnumber[MAX_LENGTH]; 
    int number;

    mqd_t *queues;

    srand(time(NULL));

    if(argc != 2) usage();
    n = atoi(argv[1]);
    if(n<=0 || n>=100) usage();

    queues = (mqd_t*)malloc(sizeof(mqd_t) * n);
    if(queues == NULL) ERR("malloc");

    for(i = 0; i < n; i++) {
        queues[i] = create_message_queue(i+1);
    }

    while(fgets(strnumber, MAX_LENGTH, stdin)!=NULL) {
        number = (uint8_t)atoi(strnumber);
        if(number<=0) continue;

        int randomQueue = rand()%n;
        if(TEMP_FAILURE_RETRY(mq_send(queues[randomQueue], (const char *)&number, 1, (unsigned)randomQueue))) ERR("mq_send");
    }

    for(i = 0; i < n; i++) {
        delete_message_queue(queues[i], i+1);
    }

    free(queues);

    return EXIT_SUCCESS;
}

当我执行我的代码时,什么也没有发生:

什么都没发生

或者我有这样的错误:

错误的文件描述符

您将指向queue (这是一个局部变量)的指针传递给线程(通过not.sigev_value.sival_ptr ),该线程在该变量超出 scope 之后运行。 所以它得到一个悬空指针。

通过值传递描述符(如果它适合sigval ;它应该),或者将其存储在堆上(使用new / malloc )并传递指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM