diff --git a/src/System.Device.Gpio/Interop/Unix/libgpiod/V2/Proxies/EdgeEventBuffer.cs b/src/System.Device.Gpio/Interop/Unix/libgpiod/V2/Proxies/EdgeEventBuffer.cs index 38ead593b7..898001de25 100644 --- a/src/System.Device.Gpio/Interop/Unix/libgpiod/V2/Proxies/EdgeEventBuffer.cs +++ b/src/System.Device.Gpio/Interop/Unix/libgpiod/V2/Proxies/EdgeEventBuffer.cs @@ -52,6 +52,13 @@ public EdgeEvent GetEvent(ulong index) return CallLibgpiod(() => { using EdgeEventNotFreeable edgeEventHandle = LibgpiodV2.gpiod_edge_event_buffer_get_event(Handle, index); + // gpiod_edge_event_buffer_get_event returns NULL when the requested index is not populated in the buffer. Passing a null pointer + // to gpiod_edge_event_copy triggers a native assertion (assert(event)) which aborts the process. Guard against it here. + if (edgeEventHandle.IsInvalid) + { + throw new GpiodException($"Edge event at index {index} is not populated in the buffer."); + } + // Since events are tied to the buffer instance, different threads may not operate on the buffer and any associated events at the same // time. Events can be copied using ::gpiod_edge_event_copy in order to create a standalone objects - which each may safely be used from // a different thread concurrently. diff --git a/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs b/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs index 49bfc5e76b..51a3725687 100644 --- a/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs +++ b/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs @@ -219,10 +219,15 @@ private void HandleEdgeEventsOfRequestInLoop(LineRequest request) int numberOfReadEvents = request.ReadEdgeEvents(edgeEventBuffer); - for (int i = 0; i < numberOfReadEvents; i++) + // Bound iteration by the number of events actually stored in the buffer. The value returned by ReadEdgeEvents can exceed the + // number of events retrievable from the buffer, in which case GetEvent would receive a null event from libgpiod. + int numberOfBufferedEvents = edgeEventBuffer.GetNumEvents(); + int numberOfEventsToHandle = Math.Min(numberOfReadEvents, numberOfBufferedEvents); + + for (int i = 0; i < numberOfEventsToHandle; i++) { - EdgeEvent edgeEvent = edgeEventBuffer.GetEvent((ulong)i); - HandleEdgeEvent(edgeEvent); +using EdgeEvent edgeEvent = edgeEventBuffer.GetEvent((ulong)i); +HandleEdgeEvent(edgeEvent); } } }