From 39860dc5943ac2478a859e08fee3e3b4f8d326c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:05:40 +0000 Subject: [PATCH 1/4] Initial plan From 5a8000513722f6492e146e05f892189e24030096 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:07:09 +0000 Subject: [PATCH 2/4] Guard against null edge event in LibGpiodV2 to prevent native abort Co-authored-by: krwq <660048+krwq@users.noreply.github.com> --- .../Interop/Unix/libgpiod/V2/Proxies/EdgeEventBuffer.cs | 7 +++++++ .../System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) 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..af5314beda 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($"Could not get edge event at index {index}: {LastErr.GetMsg()}"); + } + // 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..9fabef42f7 100644 --- a/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs +++ b/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs @@ -219,7 +219,12 @@ 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); From b0170cda36c9eab7b2921e1ee501cc91df27826e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:11:14 +0000 Subject: [PATCH 3/4] Refine null edge event error message per review Co-authored-by: krwq <660048+krwq@users.noreply.github.com> --- .../Interop/Unix/libgpiod/V2/Proxies/EdgeEventBuffer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 af5314beda..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 @@ -56,7 +56,7 @@ public EdgeEvent GetEvent(ulong index) // 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($"Could not get edge event at index {index}: {LastErr.GetMsg()}"); + 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 From f45c48859b98a6612fc06bf611ddf940fe6bc595 Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Thu, 27 Aug 2026 17:45:19 +0200 Subject: [PATCH 4/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 9fabef42f7..51a3725687 100644 --- a/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs +++ b/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodV2EventObserver.cs @@ -226,8 +226,8 @@ private void HandleEdgeEventsOfRequestInLoop(LineRequest request) for (int i = 0; i < numberOfEventsToHandle; i++) { - EdgeEvent edgeEvent = edgeEventBuffer.GetEvent((ulong)i); - HandleEdgeEvent(edgeEvent); +using EdgeEvent edgeEvent = edgeEventBuffer.GetEvent((ulong)i); +HandleEdgeEvent(edgeEvent); } } }