boost.interprocess: несовместимость между managed_shared_memory и managed_external_buffer? - PullRequest
0 голосов
/ 16 октября 2019

Boost.interprocess имеет четыре различных типа управляемой памяти: managed_shared_memory, managed_mapped_file, managed_heap_memory и managed_external_buffer. Бустерная документация, хотя это явно не указано, указывает на то, что они должны взаимодействовать друг с другом. Учитывая, что все четыре наследуют от ipcdetail::basic_managed_memory_impl, это выглядит как разумное предположение.

Следующий код создает объект managed_shared_memory, заполняет его, затем повторно отображает объект файла обратно как manage_mapped_file ипроверяет содержание. Это работает нормально, как и ожидалось, потому что оба по существу делают одно и то же (отображая файл в память).

Затем он закрывает все и считывает содержимое объекта файла в локальный буфер, которыйзатем используется для создания managed_external_buffer объекта. Попытки вызвать метод find() в управляемой памяти приводят к SEGV.

Когда я использую mutex_family вместо null_mutex_family, вместо SEGV происходит зависание. strace показывает, что он находится в вызове futex(..., FUTEX_WAIT_PRIVATE, ...).

В сеансе отладки, отходя от метода find(), я обнаружил, что offset_ptr имеет неправильное смещение, которое вызывает SEGV. Очевидно, этого не происходит при использовании managed_mapped_file.

Не верно ли мое предположение о совместимости? В расширенной документации есть пример кода, в котором заполняется сегмент managed_heap_memory, а затем копия его содержимого впоследствии используется как managed_external_buffer. Было ли это подразумевать некоторые ограничения взаимодействия между управляемыми типами памяти?

// gcc-7.3.0
// boost-1.68

#include <iostream>
#include <fstream>
#include <string>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/managed_external_buffer.hpp>

using std::cout;
using std::endl;

using namespace boost::interprocess;

namespace ipc {
    // standardize implementations
    using msm = basic_managed_shared_memory<  char, rbtree_best_fit<null_mutex_family, offset_ptr<void>>, iset_index>;
    using mmf = basic_managed_mapped_file<    char, rbtree_best_fit<null_mutex_family, offset_ptr<void>>, iset_index>;
    using meb = basic_managed_external_buffer<char, rbtree_best_fit<null_mutex_family, offset_ptr<void>>, iset_index>;
}

int main () {
    struct shm_remover {
        shm_remover  () { shared_memory_object::remove("__myint__"); }
        ~shm_remover () { shared_memory_object::remove("__myint__"); }
    } remover;

    {
        cout << "original:" << endl;
        ipc::msm original(create_only, "__myint__", 1024);
        int *i0 = original.construct<int>("my_int")(42);
        cout << "    *i0=" << *i0 << endl;

        // map in shared file that was just created
        // exact path is OS specific: /dev/shm for linux
        cout << "mapped_file:" << endl;
        ipc::mmf managed_mapped_file(open_read_only, "/dev/shm/__myint__");
        const int *i1 = (managed_mapped_file.find<int>("my_int")).first;
        cout << "    *i1=" << *i1 << endl;
    }

    // copy contents of shared file to local buffer
    std::ifstream file("/dev/shm/__myint__", std::ios::binary);
    std::string buffer(1024, '\0');
    file.read(&buffer[0], 1024);
    file.close();

    cout << "external_buffer:" << endl;
    ipc::meb managed_external_buffer(open_only, static_cast<void *>(&buffer[0]), 1024);
    // SEGV here
    auto result = managed_external_buffer.find<int>("my_int");
    cout << "    after find()" << endl;
    const int *i2 = result.first;
    cout << "    *i2=" << *i2 << endl;

    return 0;
}

...