On Wed, Sep 28, 2022 at 5:17 PM Viresh Kumar viresh.kumar@linaro.org wrote:
On 28-09-22, 14:20, Bartosz Golaszewski wrote:
Ok, so this is not correct. The doc for gpiod_edge_event_buffer_get_event() says:
- @return Pointer to an event stored in the buffer. The lifetime of the
- event is tied to the buffer object. Users must not free the event
- returned by this function.
We make no guarantees that the address returned by gpiod_edge_event_buffer_get_event() will still be valid after a call to gpiod_line_request_read_edge_event(). In fact the doc for the latter says:
- @note Any exising events in the buffer are overwritten. This is not an
append operation.
So we're being clear that after a call to gpiod_line_request_read_edge_event(), all previously returned edge event pointers are invalid unless the objects to which they point were explicitly copied.
Current implementation does indeed work like what you describe but that behavior is not "contractually" guaranteed and can change even between minor releases.
In C++ if you do:
const edge_event& ev = buffer.get_event(0); request.read_edge_event(buffer); std::cout << ev << std::endl;
You risk a segfault.
My understanding is that Rust should not allow a crash in this situation by design.
Hmm, so what exactly do we want to do here then ?
- Don't allow events to be referenced ? i.e. make event_clone() the default behavior ?
God no, that would be wasteful.
- Don't allow read_edge_event() to be called twice for a buffer ? that will be inefficient though.
Not good either.
- Somehow guarantee that reference to all the events are dropped before issuing read_edge_event() again, else make it fail ? I am not sure how straight forward that can be though.
In C++ the preferred way is to do buffer.get_event(0) which will return a constant reference. If you store that reference as const edge_event& ev = buffer.get_event(0) and reuse it after rereading into that buffer and the program crashes - that's on you. In most cases you should just do buffer.get_event(0).line_offset() etc. If you do:
edge_event event = buffer.get_event(0);
You'll copy the event and it will survive the overwriting of the buffer.
I'm a Rust beginner but my understanding is that the whole idea of the language design is to *not* allow a situation where the program can crash. It should be detected at build-time. We must not rely on "contracts" defined by documentation.
Is there a way to invalidate a reference in Rust? Have a small (cheap) object in the buffer which the event references and which would get dropped when reading into the buffer?
Bart