3

I am trying to communicate with forked child process using message queue from boost interprocess library. When child process calls receive it causes exception with message

boost::interprocess_exception::library_error

I am using GCC 6.3 on Debian 9 x64.

#include <iostream>
#include <unistd.h>
#include <boost/interprocess/ipc/message_queue.hpp>
#include <memory>

int main(int argc, char* argv[])
{
    using namespace boost::interprocess;

    const char* name = "foo-552b8ae9-6037-4b77-aa0d-d4dc9dad790b";
    const int max_num_msg = 100;
    const int max_msg_size = 32;
    bool is_child = false;

    message_queue::remove(name);
    auto mq = std::make_unique<message_queue>(create_only, name, max_num_msg, max_msg_size);

    auto child_pid = fork();
    if (child_pid == -1)
    {
        std::cout << "fork failed" << std::endl;
        return -1;
    }
    else if (child_pid == 0)
    {
        is_child = true;
    }

    if (is_child)
    {
        // does child needs to reopen it?
        mq.reset( new message_queue(open_only, name) );
    }

    int send_num = 0;
    while(true)
    {
        unsigned int priority = 0;
        if (is_child)
        {
            message_queue::size_type bytes = 0;
            try
            {
                int num;
                // Always throws. What is wrong ???????
                mq->receive(&num, sizeof(num), bytes, priority);
                std::cout <<  num << std::endl;
            }
            catch(const std::exception& e)
            {
                std::cout << "Receive caused execption " << e.what() << std::endl;
            }
            sleep(1);
        }
        else
        {
            mq->send(&send_num, sizeof(send_num), priority);
            send_num++;
            sleep(5);
        }
    }


    return 0;
}

Also, in child process is it required to reopen the message queue created by the parent process? I tried it both ways and neither worked. I am getting the same exception on receive.

quantum_well
  • 751
  • 8
  • 15

1 Answers1

1

The problem is that your receive buffer is smaller than max_msg_size. Assuming 4-byte integers, this should work:

int num[8];
mq.receive(num, sizeof(num), bytes, priority);
std::cout << *num << std::endl;

Also, I see no reason to play fast and loose with the actual queue instance. Just create it per process:

#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <iostream>
#include <memory>
#include <unistd.h>

int main() {
    namespace bip = boost::interprocess;

    const char *name = "foo-552b8ae9-6037-4b77-aa0d-d4dc9dad790b";
    {
        const int max_num_msg = 100;
        const int max_msg_size = 32;
        bip::message_queue::remove(name);
        bip::message_queue mq(bip::create_only, name, max_num_msg, max_msg_size);
    }

    auto child_pid = fork();
    if (child_pid == -1) {
        std::cout << "fork failed" << std::endl;
        return -1;
    }
    bip::message_queue mq(bip::open_only, name);

    if (bool const is_child = (child_pid == 0)) {
        while (true) {
            unsigned int priority = 0;
            bip::message_queue::size_type bytes = 0;

            try {
                int num[8];
                mq.receive(num, sizeof(num), bytes, priority);
                std::cout << *num << std::endl;
            } catch (const bip::interprocess_exception &e) {
                std::cout << "Receive caused execption " << boost::diagnostic_information(e, true) << std::endl;
            }
            sleep(1);
        }
    } else {
        // parent
        int send_num = 0;
        while (true) {
            unsigned int priority = 0;

            mq.send(&send_num, sizeof(send_num), priority);
            send_num++;
            sleep(5);
        }
    }
}
sehe
  • 328,274
  • 43
  • 416
  • 565
  • So the receive buffer size must be at least max message size. Not very intuitive. – quantum_well Aug 31 '18 at 23:54
  • Agreed, Haven't found documentation for it either, just something I arrived at by experimenting. It does make a modicum of sense, if you consider that the implementation wants to avoid double buffering. – sehe Aug 31 '18 at 23:55