impulsar el método de búsqueda de memoria compartida compartida () ata
Avatar S.K
Pregunta contestada

impulsar el método de búsqueda de memoria compartida compartida () atascado en mutex para siempre

Tengo el siguiente programa y esto es lo que se supone que debe hacer:

  • abrir/crear un segmento de memoria compartida
  • llame a find() en ese segmento de memoria compartida administrada para buscar un objeto
  • si no se encuentra, instanciarlo
  • si lo encuentra, simplemente descargue el contenido

Lo pruebo de la siguiente manera:

  • ejecutar una instancia de este programa en una ventana
  • crea el segmento de memoria compartida y también instancia el objeto
  • espera para siempre (no estoy seguro de si es necesario, simplemente lo agregué para asegurarme de que Linux no libere esa memoria compartida tan pronto como el programa finalice)
  • ejecutar otra instancia del mismo programa y esperar que encuentre el objeto (y aquí es donde se atasca)

    class data_store {
    public:
        data_store(uint32_t id, const char *name, bool safe) {
            id_ = id;
            strncpy(name_, name, sizeof(name_));
            safe_ = safe;
        }
        ~data_store() {}
        uint32_t id(void) const { return id_; }
        const char *name(void) const { return name_; }
    
    private:
        char name_[32];
        bool safe_;
        uint32_t id_;
    };
    int
    main ()
    {
        managed_shared_memory    *test_shmseg;
        data_store               *ds;
    
        try {
            test_shmseg = new managed_shared_memory(open_or_create, "seg2", 2048);
        } catch (std::exception ex) {
            std::cerr << ex.what() << '\n';
        }
        assert(test_shmseg != NULL);
    
        try {
            std::cout << "Free size " << test_shmseg->get_free_memory() << std::endl;    
            std::pair<data_store *, std::size_t> dsdir =
                test_shmseg->find<data_store>("Datastore");
            if (dsdir.first == NULL) {
                // instantiate a data store
                std::cout << "Instantiating data store" << std::endl;
                ds =
                    test_shmseg->construct<data_store>("DataStore")(1,
                                                                    std::string("ds").c_str(), true);
                if (ds == NULL) {
                    std::cout << "Failed to construct Datastore" << std::endl;
                    exit(1);
                }
            } else {
                std::cout << "Datastore found" << std::endl;
                ds = dsdir.first;
            }
            std::cout << "Data store id " << ds->id() << std::endl;
            std::cout << "Data store name " << ds->name() << std::endl;
        }  catch (boost::interprocess::bad_alloc &ex) {
            std::cerr << ex.what() << '\n';
        }
        while (1);   // wait for the other instance of this program to find the created segment and dump contents
    }
    

    No puedo entender por qué la segunda instancia de esto puede abrir el segmento de memoria compartida pero siempre se atasca en un mutex

    (gdb) bt
    #0  0x00007ffff7bcd42d in __lll_lock_wait () from /lib64/libpthread.so.0
    #1  0x00007ffff7bc8de6 in _L_lock_870 () from /lib64/libpthread.so.0
    #2  0x00007ffff7bc8cdf in pthread_mutex_lock () from /lib64/libpthread.so.0
    #3  0x0000000000403d6d in boost::interprocess::ipcdetail::posix_recursive_mutex::lock (this=0x7ffff7ff8070)
        at /usr/include/boost/interprocess/sync/posix/recursive_mutex.hpp:90
    #4  0x0000000000403e52 in boost::interprocess::interprocess_recursive_mutex::lock (this=0x7ffff7ff8070)
        at /usr/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp:163
    #5  0x0000000000408457 in boost::interprocess::scoped_lock<boost::interprocess::interprocess_recursive_mutex>::lock
        (this=0x7fffffffdf30) at /usr/include/boost/interprocess/sync/scoped_lock.hpp:284
    #6  0x00000000004073b0 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_get_lock (this=0x7ffff7ff8010, use_lock=true)
        at /usr/include/boost/interprocess/segment_manager.hpp:1315
    #7  0x00000000004069ea in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_generic_find<char> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", index=..., table=...,
        length=@0x7fffffffe098: 0, is_intrusive=..., use_lock=true)
        at /usr/include/boost/interprocess/segment_manager.hpp:844
    #8  0x0000000000405f1e in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::priv_find_impl<data_store> (this=0x7ffff7ff8010, name=0x41c4a5 "Datastore", lock=true)
        at /usr/include/boost/interprocess/segment_manager.hpp:724
    #9  0x0000000000405309 in boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::find<data_store> (this=0x7ffff7ff8010, name=...)
        at /usr/include/boost/interprocess/segment_manager.hpp:434
    #10 0x00000000004044ea in boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul>::find<data_store> (this=0x63ec20, name=...)
        at /usr/include/boost/interprocess/detail/managed_memory_impl.hpp:346
    #11 0x00000000004040f7 in boost::interprocess::basic_managed_shared_memory<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::int---Type <return> to continue, or q <return> to quit---
    erprocess::iset_index>::find<data_store> (this=0x63ec20, name=...)
        at /usr/include/boost/interprocess/managed_shared_memory.hpp:212
    

Cualquier ayuda es apreciada.

Mostrar la mejor respuesta

  • espera para siempre (no estoy seguro de si es necesario, simplemente lo agregué para asegurarme de que Linux no libere esa memoria compartida tan pronto como el programa finalice)

No, eso no es obligatorio. La memoria compartida es compartida. Permanece a menos que lo remove() explícitamente.

Revisión

Tiene al menos una incoherencia: el nombre del objeto es "Datastore" o "DataStore"; asegúrese de que coincida con la ortografía.

Aparte de eso, creo

  • es posible que no desee una asignación de "estilo de matriz", que está utilizando (¿sin darse cuenta?)
  • Es mejor que uses find_or_construct, que elimina la posible condición de carrera (ventana de tiempo de verificación frente a tiempo de uso entre la búsqueda y la creación de una nueva instancia, respectivamente).

Aparte de eso, no veo ninguna razón inmediata para colgar. Tal vez pueda intentar eliminar el objeto compartido una vez, manualmente, y usar el siguiente programa simplificado para volver a probar:

#include <boost/interprocess/managed_shared_memory.hpp>
#include <iostream>
#include <cassert>
namespace bip = boost::interprocess;

class data_store {
  public:
    data_store(uint32_t id, const char *name, bool safe) :
        id_(id), safe_(safe)
    {
        id_ = id;
        assert(name && strlen(name) < (sizeof(name_)-1));
        strncpy(name_, name, sizeof(name_));
        safe_ = safe;
    }

    uint32_t   id()    const { return id_; }
    const char *name() const { return name_; }

  private:
    char name_[32] = {0};
    uint32_t id_;
    bool safe_;
};

int main () try {
    bip::managed_shared_memory seg(bip::open_or_create, "seg2", 2048);
    data_store ds = *seg.find_or_construct<data_store>("DataStore")(1, "ds", true);
    std::cout << "Free size " << seg.get_free_memory() << std::endl;    
    std::cout << "Data store name " << ds.name() << std::endl;
} catch (std::exception ex) {
    std::cerr << ex.what() << '\n';
}

Contiene algunas correcciones de estilo, así como la afirmación adicional sobre la longitud del nombre.

Vive en Coliru

Nota: En Coliru, use managed_mapped_file en su lugar porque manged_shared_memory no está disponible en Coliru.

Impresiones:

Free size 1712
Data store name ds
-rw-r--r-- 1 2001 2000 2.0K Mar  5 12:26 seg2
Free size 1712
Data store name ds

Avatar S.K

Gracias... esto funcionó... eliminé el segmento existente y arreglé el nombre del objeto para que fuera consistente entre DataStore/Datastore y eso funcionó. Esperaba no quedarme atascado así si el objeto aún no existe.

Si eliminar el segmento era el paso esencial, podría significar que se bloqueó un proceso con el mutex incrustado bloqueado. No existe una solución real (portátil) para esto: stackoverflow.com/questions/15772768/…