Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPIOController (PinChangeEventHandler): Assigning a PinChangeEventHandler callback or Controller.OpenPin() causes "Segmentation Error" #2273

Closed
PRIMETSS opened this issue Jan 29, 2024 · 20 comments
Labels
bug Something isn't working Needs: Author Feedback We are waiting for author to react to feedback (action required) untriaged

Comments

@PRIMETSS
Copy link

Using Latest stable release v3.1.0 & 3.2.0-prerelease.24077.2 & current repo Main (29/Jan/2024)
Creating a console App with

After moving from a working (older) to latest stable SDK & OpenWRT on RiPi Compute Module 4.
'Segmentation fault' happens when assign the ValueChanged callback.
This project had been running fine with previous version(s) & GPIO buttons were working.

_gpioPinButtonUp.ValueChanged += GpioPinButtonUp_ValueChanged

Using:
Dotnet SDK v8.101 (Alpine: dotnet-sdk-8.0.101-linux-musl-arm64) [on RPi ComputeModule CM4]
OpenWRT v23.05.2 YES
	Prev: (GPIO event working [hw buttons])
		Dotnet v8.0.100-rc.2.23502.2
		OpenWRT SNAPSHOT r24111-66f6c20e45

To replicate I build a simple console app, add dependency System.Device.Gpio (v3.1.0, tried right back to 2.2 & above preview versions and current Repo's Main branch) and GPIOController and GPIOPin, assign a callback to Pins ValueChanged event.

Build & Run App on RPi CM4 and get "Segmentation fault" after trying to assign the call back.
image

Have also tried the LibGpiodDriver when building the GPIO controller.

var LinuxLibGpioDriver = new LibGpiodDriver(gpioChip: 0, LibGpiodDriverVersion.V1);
var controller = new GpioController(PinNumberingScheme.Logical, LinuxLibGpioDriver);

Did a strace and get this which might shine some light?

Looks for Library OK:
image

Fault:
image

Code:
image

Remark out the Event Callback assign, and runs as expected.
//_Pin.ValueChanged += GpioPinButtonUp_ValueChanged;
Has something change recently with assigning callbacks in dotnet or is it a kernal/linux lib issue?

@PRIMETSS PRIMETSS added the bug Something isn't working label Jan 29, 2024
@ghost ghost added the untriaged label Jan 29, 2024
@PRIMETSS PRIMETSS changed the title GPIOController (PinChangeEventHandler): Assigning a PinChangeEventHandler callback causes "Segmentation Error" GPIOController (PinChangeEventHandler): Assigning a PinChangeEventHandler callback or Controller.OpenPin() causes "Segmentation Error" Jan 29, 2024
@PRIMETSS
Copy link
Author

Also get 'Segmentation Error' calling

Controller.OpenPin(pin);

Code:

using System;
using System.Device.Gpio;
using System.Threading;
using System.Device.Gpio.Drivers;

Console.WriteLine("Blinking LED. Press Ctrl+C to end.");

int pin = 5;

Console.WriteLine("======> Sleeping for remote Debugger connect."); // Didnt work
Thread.Sleep(30000);

Console.WriteLine("======> Creating Controller.");

var LinuxLibGpioDriver = new LibGpiodDriver(gpioChip: 0, LibGpiodDriverVersion.V1);
Console.WriteLine($"LinuxLibGpioDriver created {LinuxLibGpioDriver}");

var controller = new GpioController(PinNumberingScheme.Logical, LinuxLibGpioDriver);
Console.WriteLine($"GpioController created Sch:{controller.NumberingScheme} Pins:{controller.PinCount}");

Console.WriteLine($"About to open Pin {pin} PinMode.Input");
var _Pin = controller.OpenPin(pin, PinMode.Input);
Console.WriteLine($"======> PinCreated {_Pin.PinNumber}");

Console.WriteLine("======> Assigning event handler.");
//_Pin.ValueChanged += GpioPinButtonUp_ValueChanged;
Console.WriteLine("Assigned event handler.");

bool ledOn = true;
while (true)
{
    //controller.Write(pin, ((ledOn) ? PinValue.High : PinValue.Low));
    var v = controller.Read(pin);

    Thread.Sleep(1000);
    ledOn = !ledOn;
}


void GpioPinButtonUp_ValueChanged(object sender, PinValueChangedEventArgs pinValueChangedEventArgs)
{
}

image
STRACE:
image

@PRIMETSS
Copy link
Author

Ahh I think its a broken libgpiod library or gpiod-tools?
image

@huesla
Copy link
Contributor

huesla commented Jan 29, 2024

The "gpioinfo" command failing isn't a good sign, and it may correlate to your problem. To find the root cause, it's better to begin with a functioning state and make small changes gradually -> note versions of the working .NET Runtime / libgpiod combination -> upgrade to NET8 -> check whether it works -> upgrade libgpiod (see here) -> if all still works the issue probably comes with updating OpenWRT (some Linux driver maybe).

@pgrawehr
Copy link
Contributor

What is the exact operating system you're running? I've been working with LibGpiod on a Raspberry Pi 4 for years now and never saw such a problem.

@PRIMETSS
Copy link
Author

PRIMETSS commented Jan 29, 2024

OpenWRT, (muscl-linux-arm64) which is a running on Raspberry Pi Compute Model CM4.

Thankyou! I have another RPi CM4 dev board (prev working GPIO OS & Dotnet) here that I will investigate LibGpiod functionally on.
As GPIO through Dotnet was working on this board/version I assume it was using the old deprecated SYSFS file system GPIO functionality.

But if OK, guess I will wipe and load with all current stable and see if LibGpiod works.

@WillThisRun
Copy link

I have a similar problem when I call Controller.OpenPin() I also get a segmentation fault. This happens with System.Device.Gpio v3.1.0. However if I downgrade it to version 3.0.0 all is working as it should.

I'm running a .Net 8 application on a Variscite Dart-6UL module. Which has an NXP iMX6UL ARM Cortex-A7 processor. The OS is Debian 12 (Bookworm), custom build. Last updated on 23 January 2024.

Unfortunately I currently don't have the time to investigate it much further.

The "gpioinfo" console command does give the listing of all gpio lines.
Libgpiod2 has version "1.6.3-1+b3"

@huesla
Copy link
Contributor

huesla commented Jan 29, 2024

However if I downgrade it to version 3.0.0 all is working as it should.

One diff between the versions is that dotnet iot explicitly uses libgpiod.so.2 (instead of libgpiod.so that points to whatever latest installed version) and maybe something is off with the libgpiod.so.2 file.
I think the simplest way to tell whether the issue lies within libgpiod or something from the .NET world is to test it with some C code.

  1. Find installed libgpiod libraries: sudo find / -iname "*libgpiod.so*"
  2. Create small C program
    gpio-read-libgpiod2.c.txt
    or for libgpiod.so.3
    gpio-read-libgpiod3.c.txt
  3. link and compile against libgpiod:
    gcc gpio-read-libgpiod2.c -l:libgpiod.so.2 -o gpio-read-libgpiod2
  4. execute: ./gpio-read-libgpiod2

@PRIMETSS
Copy link
Author

Apologies!

I have traced this issue to a installed 'gpiod-tools' to help gather info on GPIO Controller
This installs a dependency 'libgpiod' which causes the "Segmentation Fault"
I did this on the 'old' previously working board (which was working) and it to had same issue!
Removing gpiod-tools stopped this issue happening.

Need now to more forward and move on with migrating to the newer System.Device.GPIO library that uses the newer IOCTL LibGpiodDriver and see how go.

[I'll report back, as have a hunch I'm going to hit this issue again...]

@PRIMETSS
Copy link
Author

PRIMETSS commented Jan 30, 2024

[Update]
Remove kernal module 'libgpiod' (v1.6.4-1) reverts back to using non IOCTL interface works no crash.
Install 'libgpiod' (v1.6.4-1) and use constructor parms

var LinuxLibGpioDriver = new LibGpiodDriver(gpioChip: 1, LibGpiodDriverVersion.V1);
Console.WriteLine($"LinuxGPIO created {LinuxLibGpioDriver}");
this._gpioController = new GpioController(PinNumberingScheme.Logical, LinuxLibGpioDriver);

Segmentation Fault re-occurs.

So I'm assuming this is a problem in the implementation of BusyBox Linux libgpiod library.....?
I'll investigate more and raise and issue to OpenWRT

[I'm happy to close this issue (if other contributors agree)]
@WillThisRun : Ref notes above might help your issue?
@huesla : Thanks Will investigate more!

![image](https://github.com/dotnet/iot/assets/11331370/e299adc5-d834-404a-8193-3ccaf19997e2)

[Update2]
Believe issue is OpenWRT is still bundling libgpiod v1.6, but dotnet is targeting latest v2.1 assume? 

https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/
![image](https://github.com/dotnet/iot/assets/11331370/fe6c75a3-38ed-46b0-8a21-d54687ab51c8)

@PRIMETSS PRIMETSS reopened this Jan 30, 2024
@WillThisRun
Copy link

I compiled that libgpio2 test, I did have to downgrade the Libgpiod2 from version "1.6.3-1+b3" to "1.6.2-1" in order to get libgpiod-dev installed to have the required header files.

The System.Device.Gpio v3.1.0 still failed with this other libgpio2 version. The test in native compiled C however does work:

root@DNR00ZZ00A0AA75:~/test# ./gpio-read-libgpiod2
GPIO 24 is 0

@huesla
Copy link
Contributor

huesla commented Jan 30, 2024

The System.Device.Gpio v3.1.0 still failed with this other libgpio2 version.

If the C program works and if it is really linked to ".so.2", it strongly suggests a bug in dotnet iot. It's weird though, because LibGpiodDriver gets used a lot. I myself use it on RPI OS that is also Debian 12 based. I just tested it with .NET7 and 8 with both libgpiod versions, 1.6 and 2.1, which worked fine.
@WillThisRun What SDK / Runtime versions do you use?

@huesla
Copy link
Contributor

huesla commented Jan 30, 2024

[Update]
Remove kernal module 'libgpiod' (v1.6.4-1) reverts back to using non IOCTL interface works no crash.

When libgpiod is not installed, dotnet iot falls back to the SysFsDriver, which avoids the use of the seemingly broken libgpiod , or whatever is behind it's curtain, on your system. You could try removing any libgpiod files and build it yourself see here

[Update2]
Believe issue is OpenWRT is still bundling libgpiod v1.6, but dotnet is targeting latest v2.1 assume?

That depends on what dotnet iot version you are using. dotnet-iot 3.1 supports libgpiod v1.6, latest master of dotnet-iot supports libgpiod v2.1 and lower.

@WillThisRun
Copy link

Strange, the problem seems to be with the pinnumbers. I used to just keep numbering them and just use pin 135 for example. But it no longer supports that and gives me a Segmentation fault. I will have to change my code to actually use chip and pin.
Because I used to have the lazy-mans init: GpioController gpioController = new();

So at least for me it seems to be a user error, which was allowed on other versions.
Though I do feel that a segmentation fault on the part of the libgpiod is a bit harsh.
Thank you all for helping me realize my mistake.

@krwq
Copy link
Member

krwq commented Feb 8, 2024

[Triage] @PRIMETSS @WillThisRun @huesla can you clarify the issue here a bit? Is this a single issue or more than one issue? Can you write what OS and libgpiod versions do you have installed? Are you using 64 or 32bit OS? What do we need to reproduce this? Can you share at minimum:

  • cat /etc/os-release
  • cat /proc/cpuinfo
  • apt list --installed | grep libgpiod
  • ls -las /lib/**/libgpiod.*

@PRIMETSS
Copy link
Author

PRIMETSS commented Feb 8, 2024

Apologies I should have supplied

root@RMS-HEAT-TRIAL:~# cat /etc/os-release NAME="OpenWrt" VERSION="23.05.2" ID="openwrt" ID_LIKE="lede openwrt" PRETTY_NAME="OpenWrt 23.05.2" VERSION_ID="23.05.2" HOME_URL="https://openwrt.org/" BUG_URL="https://bugs.openwrt.org/" SUPPORT_URL="https://forum.openwrt.org/" BUILD_ID="r23630-842932a63d" OPENWRT_BOARD="bcm27xx/bcm2711" OPENWRT_ARCH="aarch64_cortex-a72" OPENWRT_TAINTS="" OPENWRT_DEVICE_MANUFACTURER="OpenWrt" OPENWRT_DEVICE_MANUFACTURER_URL="https://openwrt.org/" OPENWRT_DEVICE_PRODUCT="Generic" OPENWRT_DEVICE_REVISION="v0" OPENWRT_RELEASE="OpenWrt 23.05.2 r23630-842932a63d"

`
root@RMS-HEAT-TRIAL:~# cat /proc/cpuinfo
processor : 0
BogoMIPS : 108.00
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd08
CPU revision : 3

processor : 1
BogoMIPS : 108.00
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd08
CPU revision : 3

processor : 2
BogoMIPS : 108.00
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd08
CPU revision : 3

processor : 3
BogoMIPS : 108.00
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd08
CPU revision : 3

Hardware : BCM2835
Revision : b03141
Serial : 10000000f958ecb0
Model : Raspberry Pi Compute Module 4 Rev 1.1
`

libgpiod - 1.6.4-1 - C library for interacting with the linux GPIO character device (gpiod stands for GPIO device).

root@RMS-HEAT-TRIAL:~# ls -las /usr/lib/libgpiod.* 0 lrwxrwxrwx 1 root root 17 Feb 9 08:54 /usr/lib/libgpiod.so.2 -> libgpiod.so.2.2.2 68 -rwxr-xr-x 1 root root 65539 Mar 11 2023 /usr/lib/libgpiod.so.2.2.2

@WillThisRun
Copy link

It is a 32bit cpu therefore it is also a 32bit OS
And my problem was that I used to just keep counting the inputs and that worked. For example:
Port 0 pin 0 is 0
Port 0 pin 31 is 31
Port 1 pin 0 is 32
Port 2 pin 4 is 68

But now I must use the port and pin numbers.

root@DNR00ZZ00A0AA75:~# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
root@DNR00ZZ00A0AA75:~# cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 5 (v7l)
BogoMIPS        : 109.09
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc07
CPU revision    : 5

Hardware        : Freescale i.MX6 Ultralite (Device Tree)
Revision        : 0000
Serial          : 0000000000000000
root@DNR00ZZ00A0AA75:~# apt list --installed | grep libgpiod

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

libgpiod-dev/oldstable,now 1.6.2-1 armhf [installed]
libgpiod2/oldstable,now 1.6.2-1 armhf [installed]
python3-libgpiod/oldstable,now 1.6.2-1 armhf [installed]
root@DNR00ZZ00A0AA75:~# ls -las /lib/**/libgpiod.*
32 -rw-r--r-- 1 root root 30054 Dec 14  2020 /lib/arm-linux-gnueabihf/libgpiod.a
 0 lrwxrwxrwx 1 root root    17 Dec 14  2020 /lib/arm-linux-gnueabihf/libgpiod.so -> libgpiod.so.2.2.2
 0 lrwxrwxrwx 1 root root    17 Dec 14  2020 /lib/arm-linux-gnueabihf/libgpiod.so.2 -> libgpiod.so.2.2.2
24 -rw-r--r-- 1 root root 21952 Dec 14  2020 /lib/arm-linux-gnueabihf/libgpiod.so.2.2.2
root@DNR00ZZ00A0AA75:~#

@PRIMETSS
Copy link
Author

[IMPORTANT]

Actually just hit the "Segmentation Error" again on a field unit we are testing. Its never had this issue.
But this unit I JUST notice was opening a GPIO Port (#GPIO6) for an input that was also been forced into an Output at boot through the deprecated SYSFS method
image

Our code Initializes the GPIOController at start up to enable some GPIO ports for physical PCB Button control.
I believe this is when the Segment Fault occurred! Crashing the app running (as a service)
So this dual use of same GPIO port using old SYSFS and the new LibGpiodDriver might be the issue
image
image

As this was the system I was using when got the issue above, I wonder if this was the cause of issues I have seen.
So, Sorry!!! It's possible this is cause. Will have to investigate, but thought I'd leave comment just in case!
I'll get back once re-confirmed the issue is still there now I have discovered this!

@pgrawehr
Copy link
Contributor

@PRIMETSS Yes, this is a known issue, see #1992. When sysfs keeps a pin open, it cannot be accessed trough libgpiod. This shouldn't cause a segfault (but rather some defined exception), but maybe that behavior is OS-dependent or otherwise tied to that specific setup.

To avoid this problem, use echo "6" > /sys/class/gpio/unexport after you're done with sysfs.

@Ellerbach
Copy link
Member

[Triage] As it seems that this is not a real issue we can directly fix and everyone found a workaround as problems were mainly related to the configuration, we will most likely close this issue if no new problem that can be fixed in this repository is open.

@Ellerbach Ellerbach added the Needs: Author Feedback We are waiting for author to react to feedback (action required) label Feb 15, 2024
Copy link
Contributor

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

@github-actions github-actions bot locked and limited conversation to collaborators Mar 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working Needs: Author Feedback We are waiting for author to react to feedback (action required) untriaged
Projects
None yet
Development

No branches or pull requests

6 participants