Hi! Mathieu Othacehe <othac...@gnu.org> skribis:
> Here's a Valgrind backtrace: > > ==97844== Thread 17: > ==97844== Invalid read of size 4 > ==97844== at 0x114465B9: zmq::msg_t::close() (in > /gnu/store/zd9lbfqa3170nsfd4177dnr38k1sjbnc-zeromq-4.3.4/lib/libzmq.so.5.2.4) First, is this function idempotent? (Is it OK to close an msg_t multiple times.) Second, remember that finalizers can run in a separate thread. Thus, you must make sure there are no other threads, such as ZMQ’s internal threads, still operating on the object when it is freed. > ==97844== by 0x3A58E98F: ??? > ==97844== by 0x489AC78: chained_finalizer (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x49A16EE: GC_invoke_finalizers (in > /gnu/store/iycnpxxrg8m9wf9w58d6zvp9sdby6m9d-libgc-7.6.12/lib/libgc.so.1.3.6) > ==97844== by 0x489AF08: scm_run_finalizers (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x489AF8C: finalization_thread_proc (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x488BB09: c_body (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x4913148: vm_regular_engine (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x49145B4: scm_call_n (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x4890BB9: scm_call_2 (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x48923B9: scm_c_with_exception_handler (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== by 0x4909C3C: scm_c_catch (in > /gnu/store/q8brh7j5mwy0hbrly6hjb1m3wwndxqc8-guile-3.0.5/lib/libguile-3.0.so.1.3.0) > ==97844== Address 0x7373313569316263 is not stack'd, malloc'd or (recently) > free'd > > > It looks like the finalizer is operating on a memory region that has > already been free'd. The documentation associated with the > finalization functions in <gc.h> says: > > /* When obj is no longer accessible, invoke */ > /* (*fn)(obj, cd). If a and b are inaccessible, and */ > /* a points to b (after disappearing links have been */ > /* made to disappear), then only a will be */ > > > As far as I understand, OBJ is the wrapped pointer to the bytevector > created in "zmq-msg-init". There's a weak reference between the pointer > and the bytevector that is introduced by "register_weak_reference" in > "bytevector->pointer". There are (roughly) three objects here: the “msg”, the pointer object, and the bytevector that pointer refers to. The bytevector may be freed when the pointer object becomes unreachable. But you probably also need a weak link from the “msg” object to the pointer object to ensure that the pointer object outlives the msg object. You also need to check the zmq::msg_t::close memory semantics: does it free the data associated with the message? If so, that’s redundant with the pointer finalizer. > My interrogation is: do I have the guarantee that the pointer and its > references are still readable from within the finalizer? The above > snippet says that FN is invoked when OBJ is unaccessible, but does this > mean its content may have already been collected? Not sure, but most likely the problem is at a higher layer. :-) If you can get a reduced test case to run under ‘rr’, that should allow you to see where the message was first freed. This is all pretty vague and general, but I HTH! Ludo’.