-
Notifications
You must be signed in to change notification settings - Fork 577
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
Callbacks registered via RegisterCallbackForPinValueChangedEvent are not getting called when pin value changes #2131
Comments
What hardware are you running this on? And is there a specific reason why you run your app in a container? This adds additional complexity. |
This is running on a custom linux arm iot platform using the azure iot edge runtime. We are using the container runtime from iot edge to deploy our application to the device. |
The callback is known to work on other platforms, so there must be something special about yours, maybe the libgpiod driver is not fully compatible. Have you tried the sysfs driver? |
When using the SysFs driver the following exception was thrown when pressing the button connected to the pin:
|
[Triage] are you forwarding pin related directories to the docker container? what's the exact command line you're using to run your container? (or at least relevant pieces to GPIO) If you can please also share dockerfile |
Here are some basic instructions how to run in the container: https://github.com/dotnet/iot/tree/main/samples/led-blink (last command line is for sysfs) |
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. |
Yes, we run the container privileged and we forwarded the directory to the container.
# final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:7.0.1-alpine3.17
ARG PROJ_NAME
ARG PORT
VOLUME /hostpipe
VOLUME /scripts
VOLUME /libsFromHost
COPY --from=build /testresults /testresults
WORKDIR /app
COPY --from=build /app .
COPY --from=build /app/CBinaries/*.so /app
EXPOSE $PORT
EXPOSE 80
# Copy repository configuration (optional)
COPY alpinehelper/etc/apk/repositories /etc/apk/repositories
# Copy our local repository
COPY alpinehelper/usr/local/repo /usr/local/repo
# Copy keys which we generated previously
COPY alpinehelper/etc/apk/keys /etc/apk/keys
RUN apk --no-cache add libmodbus libmodbus-dev
RUN echo "chmod a+r /dev/ttySTM3" > ./entrypoint.sh
RUN apk --no-cache add libgpiod-dev gpsd
RUN echo "gpsd /dev/ttySTM3 -F /var/run/gpsd.sock" >> ./entrypoint.sh
RUN echo "./${PROJ_NAME}" >> ./entrypoint.sh
RUN cat ./entrypoint.sh
RUN chmod 777 ./entrypoint.sh
ENTRYPOINT ./entrypoint.sh |
Thanks for the Dockerfile. We would also need the docker run command to see how are you volume-mounting the necessary files for sysfs driver to work. |
We are using the azure iot edge runtime to deploy and start our containers. To do that we don't provide a command but a manifest where we define modules. We tried three different things, I will list the attempts below: Attempt 1: only running privileged
Attempt 2: Binding
|
Thanks @m4schini |
We tried it as you described and the behavior for both Sysfs and libgpio is unchanged. For reference the manifests we used: Deployment manifest (/sys as device)
Deployment manifest (/sys not as device)
In addition to that we also tried to do the same with a slightly different manifest. This time instead of "Binds" we used "Mounts" with bind type: Deployment manifest
And got the following error in the iot edge agent (which is starting the container on the device)
We use, depending on what we are testing, either SysFsDriver.cs or LibGpiodDriver.cs.
We confirmed that both work inside the container with the usual command line utilities. |
[Triage] - Sorry @m4schini I know we suggested above to try sysfs but I somehow missed the part you saying that you were running on iot edge. We believe that this is a limitation of azure iot edge where you can't really volume mount the paths you need in order for sysfs driver to work. All that said, in general we usually prefer libgpiod driver as that is usually much more accurate, so I think it's worth going back to that versio instead and figure out what's wrong there. Is it just eventing that is not working for you? What I mean by this is, if you write to a pin which is connected to another pin, do you see the values changing? |
Yes we also expect the problem to be Eventing related because of the behavior we observed (inside the container):
|
I'm going on Vacation, my collegue (@ignaciocaramba) will be taking over this issue from our side. |
As a side note: private unsafe bool WasEventDetected(int pollFileDescriptor, int valueFileDescriptor, out int pinNumber, CancellationToken cancellationToken)
{
char buf;
IntPtr bufPtr = new IntPtr(&buf);
pinNumber = -1;
while (!cancellationToken.IsCancellationRequested)
{
// Wait until something happens
int waitResult = CustomInterop.CustomInterop.epoll_wait(pollFileDescriptor, out epoll_event events, 1, PollingTimeout);
if (waitResult == -1)
{
var errorCode = Marshal.GetLastWin32Error();
if (errorCode == ERROR_CODE_EINTR)
{
// ignore Interrupted system call error and retry
continue;
}
throw new IOException($"Error while waiting for pin interrupts. (ErrorCode={errorCode})");
}
if (waitResult > 0)
{
pinNumber = events.data.pinNumber;
/* WE COMMENTED OUT THIS SECTION
// This entire section is probably not necessary, but this seems to be hard to validate.
// See https://github.com/dotnet/iot/pull/914#discussion_r389924106 and issue #1024.
if (valueFileDescriptor == -1)
{
// valueFileDescriptor will be -1 when using the callback eventing. For WaitForEvent, the value will be set.
valueFileDescriptor = _devicePins[pinNumber].FileDescriptor;
}
int lseekResult = CustomInterop.CustomInterop.lseek(valueFileDescriptor, 0, SeekFlags.SEEK_SET);
if (lseekResult == -1)
{
throw new IOException("Error while trying to seek in value file.");
}
int readResult = CustomInterop.CustomInterop.read(valueFileDescriptor, bufPtr, 1);
if (readResult != 1)
{
throw new IOException("Error while trying to read value file.");
}
*/
return true;
}
}
return false;
} |
That's interesting, in particular due to the comment there. Can you check what the value of |
@pgrawehr |
@pgrawehr any updates? |
@ignaciocaramba Sorry, I didn't have time to look into this. Since it appears to be working if you comment out that block of code (whose existing comment already says that it's questionable), we could verify whether removing that would cause the other boards to break. Can you submit a PR with that piece of code commented out? That would trigger the CI run and we would see whether it directly causes any issues. CI is running a bunch of GPIO tests on actual hardware. |
@pgrawehr Pr created and All tests have passed |
The pr fixes the issue with the SysfsDriver, but our initial problem is not fixed: if instead of using Sysfs we use LibGpiod when registering a Callback via RegisterCallbackForPinValueChangedEvent and changing the value of the gpio pin, the callback is not being called. Also, is there a problem to use SysfsDriver instead of LibgpiodDriver for listening to button events? |
@ignaciocaramba You seem to have some special hardware there, and it was kind of a coincidence that it could be so easily fixed for Sysfs. When it doesn't work with libgpiod the problem is probably in the library or the hardware and there's likely nothing we can do on our side. SysFs is generally much slower than libgpiod. If you use this only for buttons, the impact will be negligible. If you need to handle events in the Kilohertz range, then sysfs might not be fast enough and you will loose events. |
Describe the bug
After registering a Callback via RegisterCallbackForPinValueChangedEvent and changing the value of the gpio pin, the callback is not being called.
We confirmed that the pin value is being changed (Controller.Read() and gpiod terminal utilities).
Steps to reproduce
The environment has
libgpiod-dev
installed.Expected behavior
The register callback shoud be called when the event happen.
Actual behavior
The register callback is not being called.
Versions used
dotnet --info
on the machine where app is being run (not applicable for self-contained apps)Image used in the build stage:
mcr.microsoft.com/dotnet/sdk:7.0-bullseye-slim-amd64
Image running in the container:
mcr.microsoft.com/dotnet/aspnet:7.0.1-alpine3.17
Version of
System.Device.Gpio
package: 3.0.0The text was updated successfully, but these errors were encountered: