pmem / libpmemobj-cpp

C++ bindings & containers for libpmemobj
https://pmem.io
Other
108 stars 76 forks source link

Handle free()/destruction failure in containers dtors #474

Open igchor opened 5 years ago

igchor commented 5 years ago

One solution is to call free_data() in delete_persistent method. This will allow to propagate exception and not abort application (if throwed inside destructor). All containers should implement this method.

Another solution is to to use pmdk add_buffer feature to reserve space for free(). The problem is with non-trivial types because we need to call destructors for those. (For trivial types we can skip destruction).

igchor commented 4 years ago

The main problem is that exception can be thrown inside of a destructor (because of tx abort). If a destructor is called from within a transaction (always true for delete_peristent) we could just catch any exception and ignore it:

~dtor()
{
   if (pmemobj_tx_stage() == TX_STAGE_WORK) {
     try {
        delete_persistent<>();
     } catch (...) {
       if (pmemobj_tx_stage() == TX_STAGE_ABORT) {} // ignore, outer transaction will see the state and also throw an exception
       else pmemobj_tx_abort();
     }
  } else {
    transaction::run([]{ delete_persistent<>();}); // XXX: should this still cause abort?
  }
}

All this code could be exposed as some generic API.

Some things to keep in mind: